omadrm/drmengine/server/src/drmrightsdb.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 12:08:35 +0200
changeset 4 fdb8e8f25c0d
parent 0 95b198f216e5
child 12 8a03a285ab14
permissions -rw-r--r--
Revision: 201001 Kit: 201004

/*
* Copyright (c) 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 the DRM Rights Database
*
*/


// INCLUDE FILES

#include <e32std.h>     // RPointerArray
#include <e32def.h>     // Type definitions
#include <hash.h>       // MD5 Algorithm
// #include <SysUtil.h>    // Disk space checking
#include <f32file.h>
#include <s32strm.h>
#include <s32file.h>
#include <caf/caf.h>
#include <symmetric.h>  // AES128CBC
#include <dcfrep.h>

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

#include "DRMCommon.h"  // DRM Error messages
#include "DRMRightsDB.h"
#include "DRMRightsData.h"
#include "DRMCommonData.h"
#include "DRMPermission.h"
#include "DRMConstraint.h"
#include "DRMRightsCleaner.h"
#include "DRMRightsServer.h"
#include "DrmKeyStorage.h"
#include "utf.h" // charconv, ConvertFromUnicodeToUtf8L
#include "drmlog.h"

#ifdef RD_DRM_RIGHTS_MANAGER_REMOVAL
#include "drmclockclient.h"
#endif // RD_DRM_RIGHTS_MANAGER_REMOVAL

/*
#include "flogger.h"


_LIT( KLogDir, "drm");
_LIT( KLogName, "backup.log");
*/

// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES

// CONSTANTS

// MACROS

// LOCAL CONSTANTS AND MACROS
#ifdef RD_MULTIPLE_DRIVE
// Backup Directory
_LIT( KBackupDir, "%c:\\private\\101F51F2\\backup\\" );
#endif


_LIT(KJavaExtension, ".jar");
_LIT(KSISExtension, ".sis");
_LIT(KROExtension, ".ro");
_LIT(KXmlExtension, ".xml");


#ifdef RD_MULTIPLE_DRIVE
_LIT(KCIDListTempDir, "%c:\\system\\temp\\");
#else
_LIT(KCIDListTempDir, "c:\\system\\temp\\");
#endif

_LIT(KRODirName, "DomainROs\\");
_LIT(KCorruptionFlagFile, "invalid");

#ifdef __DRM_OMA2
const TInt KMaxUDTDataSize = 256;
const TInt KDeviceDataSize = 256;
const TInt KDeviceDataBlock = 128;
#else
const TInt KMaxUDTDataSize = 0;
const TInt KDeviceDataSize = 0;
const TInt KDeviceDataBlock = 0;
#endif
const TInt KUdtDataPos = 4 + KDeviceDataSize;


const TInt KEncryptionKeySize = 16;
const TInt KMaxEncryptionSize = 8192;

const TInt KMaxUpdateTime = 3000000; // consider updates to be finished within
                                     // three seconds

const TUint32 KMaxTIntVal = 2147483647; // 2^31-1

// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES
LOCAL_C void CleanupData( TAny* aPtr );
LOCAL_C void WriteIntToBlock( TInt aValue, TDes8& aBlock, TInt aOffset );
LOCAL_C void DeleteObject( TAny* aObject );

// FORWARD DECLARATIONS

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

// -----------------------------------------------------------------------------
// CleanupData
// Used to catch errors and delete the file if it's needed
// -----------------------------------------------------------------------------
//
LOCAL_C void CleanupData( TAny* aPtr )
    {
    CDRMRightsDB* rdb = reinterpret_cast<CDRMRightsDB*>( aPtr );

    rdb->CleanUdtData();
    }


LOCAL_C void WriteIntToBlock( TInt aValue, TDes8& aBlock, TInt aOffset )
    {
    aBlock[aOffset] =     (aValue & 0xff000000) >> 24;
    aBlock[aOffset + 1] = (aValue & 0x00ff0000) >> 16;
    aBlock[aOffset + 2] = (aValue & 0x0000ff00) >> 8;
    aBlock[aOffset + 3] = (aValue & 0x000000ff);
    }

// ----------------------------------------------------------------------------
// DeleteObject
// Deletes the file by TFileName presented by aHandle
// ----------------------------------------------------------------------------
//
LOCAL_C void DeleteObject( TAny* aObject )
    {
    __ASSERT_DEBUG( aObject, User::Panic( _L( "DeleteObject" ), KErrArgument ) );
    MDrmKeyStorage* object = reinterpret_cast< MDrmKeyStorage* >( aObject );
    delete object;
    object = NULL;
    }


// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CDRMRightsDB::CDRMRightsDB
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CDRMRightsDB::CDRMRightsDB( RFs& aFs ) :
    iFileServer( aFs ),
    iImei( NULL ),
    iLastUpdate( Time::NullTTime() )
    {
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::ConstructL( const TDesC& aDatabasePath,
                               const TDesC8& aKey,
                               const TDesC& aImei )
    {
    TFileName name;
    TUint attr;

    DRMLOG( _L( "RDB starting..." ) );

    iDbPath = aDatabasePath.AllocL();

    // create an instance of the Hash algorithm class
    iHasher = CMD5::NewL();

    // store the key
    iKey = aKey.AllocL();

    // serial number
    iImei = aImei.AllocL();

    name.Copy( *iDbPath );
    name.Append( KCorruptionFlagFile );

    if ( iFileServer.Att( name, attr ) == KErrNone )
        {
        iFileServer.RmDir( name );
        iFileServer.Delete( name );
        DeleteDBL();
        }

    InitializeDatabaseL();
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CDRMRightsDB* CDRMRightsDB::NewLC( RFs& aFs,
                                   const TDesC& aDatabasePath,
                                   const TDesC8& aKey,
                                   const TDesC& aImei )
    {
    CDRMRightsDB* self = new( ELeave ) CDRMRightsDB( aFs );
    CleanupStack::PushL( self );
    self->ConstructL( aDatabasePath, aKey, aImei );

    return self;
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CDRMRightsDB* CDRMRightsDB::NewL( RFs& aFs,
                                  const TDesC& aDatabaseFile,
                                  const TDesC8& aKey,
                                  const TDesC& aImei )
    {
    CDRMRightsDB* self = NewLC( aFs, aDatabaseFile, aKey, aImei );
    CleanupStack::Pop();

    return self;
    };

// Destructor
CDRMRightsDB::~CDRMRightsDB()
    {
    if( iHasher )
        {
        delete iHasher;
        iHasher = NULL;
        }

    if( iDbPath )
        {
        delete iDbPath;
        iDbPath = NULL;
        }

    if( iKey )
        {
        delete iKey;
        iKey = NULL;
        }

    if( iImei )
        {
        delete iImei;
        iImei = NULL;
        }

    iMemStream.Close();

    DRMLOG( _L( "RDB Closing." ) );
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::GetDBEntryByContentIDL
// returns the rights objects connected to aContentID
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::GetDBEntryByContentIDL(
    const TDesC8& aContentID,
    RPointerArray<CDRMPermission>& aRightsList)
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;

#ifdef RD_DRM_RIGHTS_MANAGER_REMOVAL
    TTime time;
    TBool deleteAllowed = EFalse;
    TInt timeZone = 0;
    DRMClock::ESecurityLevel securityLevel;
#endif // RD_DRM_RIGHTS_MANAGER_REMOVAL
    
    GetRightsFileNameL( aContentID, path);
    
#ifdef RD_DRM_RIGHTS_MANAGER_REMOVAL
    // Get the secure time:
    RDRMClockClient client;
    error = client.Connect();
    if( !error )
        {
        client.GetSecureTime( time, timeZone, securityLevel);
        client.Close();
        if( securityLevel == DRMClock::KInsecure )
            {
            time = Time::NullTTime();
            }
        }
    else
        {
        time = Time::NullTTime();
        }

    // Delete expired:
    TRAP_IGNORE( deleteAllowed = DeleteExpiredL( path, time ) );
        
    // Check if it's possible to delete the file as well    
    if( deleteAllowed )
        {
        iFileServer.Delete( path );
        }
    
    error = KErrNone;
#endif // RD_DRM_RIGHTS_MANAGER_REMOVAL

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        if( error == KErrNotFound )
            {
            User::Leave( KErrCANoRights );
            }
        User::Leave( error );
        }

    rights->FetchAllPermissionsL( aRightsList );

    CleanupStack::PopAndDestroy(); // rights
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::GetDBEntryByContentIDL
// returns the rights object connected to aContentID and aUniqueID
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CDRMPermission* CDRMRightsDB::GetDBEntryByContentIDL(
    const TDesC8& aContentID,
    const TDRMUniqueID aUniqueID )
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;
    CDRMPermission* ro = NULL;

    if( aUniqueID > KMaxTIntVal )
        {
        User::Leave( KErrArgument );
        }

    GetRightsFileNameL( aContentID, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        if( error == KErrNotFound )
            {
            User::Leave( KErrCANoRights );
            }
        User::Leave( error );
        }

    ro = CDRMPermission::NewLC();

    rights->FetchPermissionL( *ro, aUniqueID );

    CleanupStack::Pop(); // ro
    CleanupStack::PopAndDestroy(); // rights
    return ro;
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::AddDBEntryL
// adds a new rights object into the database and uses the given aUniqueID if
// possible, if not it generates a new one
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::AddDBEntryL( const TDesC8& aContentID,
                                CDRMPermission& aRightsObject,
                                const TDesC8& aEncryptionKey,
                                TDRMUniqueID& aUniqueID )
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;
    TBuf8<16> nullDesc;
    TBuf<16> nullDesc2;
    HBufC8* oldKey = NULL;

    DRMLOG( _L( "CDRMRightsDB::AddDBEntryL ->" ) );

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();

    // the key can either be empty or it can be 16 characters:
    if( !( aEncryptionKey.Length() == KEncryptionKeySize || aEncryptionKey.Length() == 0 ) )
        {
        User::Leave(KErrArgument);
        }
        
    TBuf8<16> keyStore = aEncryptionKey;
    // TBuf8<16> authStore = aAuthenticationSeed

    // Encrypt the key
    ModifyKey( keyStore );

    // Modify also the authentication seed
    // ModifyKey( authStore )

    GetRightsFileNameL( aContentID, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );


        // Check that the keys match, if not leave with KErrArgument
        oldKey = rights->GetKeyL();
        if ( oldKey != NULL )
            {
            CleanupStack::PushL( oldKey );
            if( oldKey->Compare(keyStore) )
                {
                User::Leave(KErrArgument);
                }
            CleanupStack::PopAndDestroy( oldKey );
            }
        }

    if( error == KErrNotFound )
        {
        // This would need the other info if it was available:
        CDRMCommonData* data = CDRMCommonData::NewL( aContentID, nullDesc, aRightsObject.iRiId, nullDesc2, nullDesc );

        rights = CDRMRightsData::NewLC( data, keyStore, path, iFileServer );
        }
    else
        {
        User::LeaveIfError( error );
        }

    // Store the RO:
    rights->StoreNewPermissionL( aRightsObject, aUniqueID );

    CleanupStack::PopAndDestroy(); // rights

    DRMLOG( _L( "CDRMRightsDB::AddDBEntryL <-" ) );
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::DeleteDBEntryL
// deletes the rights object connected to aContentID and aUniqueID
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::DeleteDBEntryL( const TDesC8& aContentID,
                                   const TDRMUniqueID aUniqueID )
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;

    DRMLOG( _L( "CDRMRightsDB::DeleteDBEntryL ->" ) );

    if( aUniqueID > KMaxTIntVal )
        {
        User::Leave( KErrArgument );
        }

    GetRightsFileNameL( aContentID, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        if( error == KErrNotFound )
            {
            User::Leave( DRMCommon::ENoRights );
            }
        User::Leave( error );
        }

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();
    rights->DeletePermissionL( aUniqueID );

    CleanupStack::PopAndDestroy(); // rights

    // Check if the file can be deleted:
    CheckCleanup( path );

    DRMLOG( _L( "CDRMRightsDB::DeleteDBEntryL <-" ) );
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::DeleteDBEntryL
// deletes all rights object connected to aContenID
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::DeleteDBEntryL( const TDesC8& aContentID )
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;

    DRMLOG( _L( "CDRMRightsDB::DeleteDBEntryL (2) ->" ) );

    GetRightsFileNameL( aContentID, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        if( error == KErrNotFound )
            {
            User::Leave( DRMCommon::ENoRights );
            }
        User::Leave( error );
        }

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();
    rights->DeleteAllPermissionsL();

    CleanupStack::PopAndDestroy(); // rights

    // Check if the file can be deleted:
    CheckCleanup( path );

    DRMLOG( _L( "CDRMRightsDB::DeleteDBEntryL (2) <-" ) );
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::UpdateDBEntryL
// updates the requested rights object to the given rights object
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::UpdateDBEntryL( const TDesC8& aContentID,
                                   const CDRMPermission& aRightsObject )
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;

    DRMLOG( _L( "CDRMRightsDB::UpdateDBEntryL ->" ) );

    // Should never occur:
    if( aRightsObject.iUniqueID > KMaxTIntVal )
        {
        User::Leave( KErrArgument );
        }


    GetRightsFileNameL( aContentID, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        if( error == KErrNotFound )
            {
            User::Leave( DRMCommon::ENoRights );
            }
        User::Leave( error );
        }

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();
    rights->UpdatePermissionL( aRightsObject );

    CleanupStack::PopAndDestroy(); // rights

    DRMLOG( _L( "CDRMRightsDB::UpdateDBEntryL <-" ) );
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::ExportContentIDListL
// writes each unique content id to the requested file
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::ExportContentIDListL( TFileName& aTempFile )
    {
    __UHEAP_MARK;
    RFileWriteStream stream;


#ifndef RD_MULTIPLE_DRIVE

    User::LeaveIfError( stream.Temp( iFileServer,
                                     KCIDListTempDir,
                                     aTempFile,
                                     EFileWrite ) );

#else //RD_MULTIPLE_DRIVE

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

    TFileName cidTemp;
    cidTemp.Format( KCIDListTempDir, (TUint)driveLetter );

    User::LeaveIfError( stream.Temp( iFileServer,
                                   cidTemp,
                                   aTempFile,
                                   EFileWrite ) );

#endif

    CleanupClosePushL( stream );

    for (TInt i = 0; i < 16; i++)
        {
        CDir* files = NULL;

        TFileName path = *iDbPath;

        path.Append(i < 10 ? i + '0' : i + 'a' - 10);
        path.Append('\\');

        if ( iFileServer.GetDir(path, KEntryAttDir, ESortNone, files) == KErrNone )
            {
            TInt j;

            CleanupStack::PushL( files );

            for (j = 0; j < files->Count(); j++)
                {
                TFileName tempPath( path );

                tempPath.Append((*files)[j].iName);

                TInt error = KErrNone;
                CDRMRightsData* rights = NULL;

                TRAP( error, rights = CDRMRightsData::OpenL( tempPath, iFileServer ) );
                if( rights )
                    {
                    CleanupStack::PushL( rights );
                    }
                else
                    {
                    if( error != KErrNotFound )
                        {
                        User::Leave( error );
                        }
                    continue;
                    }

                const CDRMCommonData* data = rights->GetCommonDataL();
                stream.WriteUint16L( data->ContentID().Length() );
                stream.WriteL( data->ContentID() );

                CleanupStack::PopAndDestroy(); // rights
                }

            CleanupStack::PopAndDestroy(); // files
            }
        }

    stream.WriteUint16L(0);

    CleanupStack::PopAndDestroy(); // stream

    __UHEAP_MARKEND;
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::BackupDBL
// creates a backupfile of the current rights database and encrypts it using the
// database encryption key
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
/*
void CDRMRightsDB::BackupDBL( const TDesC& aWTFile,
                              const TDesC8& aEncryptionKey )
    {
    };
*/
// -----------------------------------------------------------------------------
// CDRMRightsDB::MergeDBL
// merges the backup database into the current database and deletes the backup
// file afterwards, any rights objects with counter base rights or non activated
// intervals are not inserted. If an equal combination of content id and unique
// id is found that object is not restored
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
/*
void CDRMRightsDB::MergeDBL()
    {
    };
*/


// -----------------------------------------------------------------------------
// CDRMRightsDB::GetDecryptionKeyL
// returns a pointer to the decryption key of the requested content id
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
HBufC8* CDRMRightsDB::GetDecryptionKeyL(
    const TDesC8& aContentID)
    {

    TFileName path;
    TInt error = KErrNone;
    HBufC8* key = NULL;
    CDRMRightsData* rights = NULL;

    GetRightsFileNameL( aContentID, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        if( error == KErrNotFound )
            {
            User::Leave( DRMCommon::ENoRights );
            }
        User::Leave( error );
        }

    key = rights->GetKeyL();

    // Decrypt the key
    ModifyKey( *key );

    CleanupStack::PopAndDestroy(); // rights

    return key;
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::DeleteDBL
// deletes the rights database and creates a new empty one in it's place
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::DeleteDBL( void )
    {
    DRMLOG( _L( "CDRMRightsDB::DeleteDBL ->" ) );

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();

    CFileMan* fileMan = CFileMan::NewL(iFileServer);
    fileMan->RmDir(*iDbPath);
    delete fileMan;

    InitializeDatabaseL();

    DRMLOG( _L( "CDRMRightsDB::DeleteDBL <-" ) );
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::GetAmountOfRightsObjectsL
// returns the amount of different content id's in the database
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt32 CDRMRightsDB::GetAmountOfRightsObjectsL()
    {
    TInt32 amount( 0 );

    for (TInt i = 0; i < 16; i++)
        {
        CDir* files = NULL;

        TFileName path = *iDbPath;

        path.Append(i < 10 ? i + '0' : i + 'a' - 10);
        path.Append('\\');

        User::LeaveIfError(
            iFileServer.GetDir(path, KEntryAttDir, ESortNone, files) );

#ifdef _DEBUG
        if ( !files )
            {
            DRMLOG( _L( "CDRMRightsDB::GetAmountOfRightsObject: GetDir returned NULL pointer!" ) );
            User::Leave( KErrGeneral );
            }
#endif

        amount += files->Count();
        delete files;
        }

    return amount;
    };



// -----------------------------------------------------------------------------
// CDRMRightsDB::AddDomainROL
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::AddDomainROL( const TDesC8& aRoId, const TDesC8& aXmlData )
    {
    RFile file;
    TFileName path;
    TPtr8 numWrite(NULL,0);
    TInt num = 0;

    DRMLOG( _L( "CDRMRightsDB::AddDomainROL ->" ) );

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();

    // Get the size and if it is zero, leave
    num = aXmlData.Size();
    if( !num )
        {
        User::Leave(KErrArgument);
        }

    // Get the filename
    GetXMLFileNameL( aRoId, path );

    // Replace whatever is in there
    User::LeaveIfError( file.Replace( iFileServer, path, EFileWrite ) );
    CleanupClosePushL( file );

    // write the size of the data
    numWrite.Set(reinterpret_cast<TUint8*>(&num), sizeof(TInt), sizeof(TInt));

    // needs a check if there is enough diskspace for sizeof(TInt) + num bytes

    User::LeaveIfError( file.Write( numWrite ) );

    // write the data
    User::LeaveIfError( file.Write( aXmlData ) );

    CleanupStack::PopAndDestroy(); // file

    DRMLOG( _L( "CDRMRightsDB::AddDomainROL <-" ) );
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::GetDomainROL
// -----------------------------------------------------------------------------
//
HBufC8* CDRMRightsDB::GetDomainROL( const TDesC8& aRoId )
    {
    RFile file;
    TFileName path;
    TPtr8 inRead(NULL,0);
    TInt num = 0;
    HBufC8* data = NULL;

    // Get the filename
    GetXMLFileNameL( aRoId, path );

    // Replace whatever is in there
    User::LeaveIfError( file.Open( iFileServer, path, EFileRead ) );
    CleanupClosePushL( file );

    // read the size of the data
    inRead.Set(reinterpret_cast<TUint8*>(&num), 0, sizeof(TInt));
    User::LeaveIfError( file.Read( inRead, sizeof(TInt) ) );

    if( num <= 0 )
        {
        User::Leave(KErrCorrupt);
        }

    data = HBufC8::NewMaxLC( num );

    // read the data
    inRead.Set( const_cast<TUint8*>( data->Ptr() ), 0, num );
    User::LeaveIfError( file.Read( inRead, num ) );

    CleanupStack::Pop(); // data
    CleanupStack::PopAndDestroy(); // Close the file
    return data;
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::DeleteDomainROL
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::DeleteDomainROL( const TDesC8& aRoId )
    {
    TFileName path;

    DRMLOG( _L( "CDRMRightsDB::DeleteDomainROL ->" ) );

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();

    // Get the filename
    GetXMLFileNameL( aRoId, path );

    User::LeaveIfError( iFileServer.Delete( path ) );

    DRMLOG( _L( "CDRMRightsDB::DeleteDomainROL <-" ) );
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::DeleteExpiredPermissionsL
// -----------------------------------------------------------------------------
//
CDRMRightsCleaner* CDRMRightsDB::DeleteExpiredPermissionsL( const TTime& aTime,
                                                            TRequestStatus& aStatus )
    {


    CDRMRightsCleaner* cleaner = CDRMRightsCleaner::NewL( iFileServer,
                                                          const_cast<CDRMRightsDB*>(this),
                                                          aStatus,
                                                          *iDbPath,
                                                          aTime);
    return cleaner;
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::NameContentL
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::NameContentL( const TDesC8& aContentId,
                                 const TDesC& aName )
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;
    CDRMCommonData* data = NULL;

    GetRightsFileNameL( aContentId, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        User::Leave( error );
        }

    data = const_cast<CDRMCommonData*>(rights->GetCommonDataL());

    data->SetContentNameL( aName );

    rights->UpdateCommonDataL( data );

    CleanupStack::PopAndDestroy(); // rights
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::ContentNameL
// -----------------------------------------------------------------------------
//
HBufC* CDRMRightsDB::ContentNameLC( const TDesC8& aContentId )
    {
    TFileName path;
    CDRMRightsData* rights( NULL );
    HBufC* name( NULL );

    GetRightsFileNameL( aContentId, path );

    rights = CDRMRightsData::OpenL( path, iFileServer );
    CleanupStack::PushL( rights );

    name = const_cast< CDRMCommonData* >( rights->GetCommonDataL() )
            ->ContentName().AllocL();

    CleanupStack::PopAndDestroy(); // rights
    CleanupStack::PushL( name );

    return name;
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::DeleteExpiredL
// -----------------------------------------------------------------------------
//
TBool CDRMRightsDB::DeleteExpiredL( const TFileName& aFileName,
                                   const TTime& aTime )
    {
    CDRMRightsData* rights = NULL;
    TInt amountLeft = -1;
    TBool retVal = EFalse;
    TBool parents = EFalse;

    DRMLOG( _L( "CDRMRightsDB::DeleteExpiredL ->" ) );

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();

    // Open the rights file
    DRMLOG( _L("Opening the file"));
    rights = CDRMRightsData::OpenLC( aFileName, iFileServer );

    DRMLOG( _L("Running Delete"));
    amountLeft = rights->DeleteExpiredPermissionsL( aTime, parents );

    DRMLOG2( _L("Checking for left RO:s %d"), amountLeft );

    // See if any permissions are left if not check if the whole file
    // can be proposed to be deleted or not, Java files require uninstallation
    // so those need to be checked
    if( !amountLeft && !parents )
        {
        // get the common data
        const CDRMCommonData* common= rights->GetCommonDataL();

        // If it is a java file, dont allow deletion
        if( !common->ContentName().Right(4).CompareF(KJavaExtension) )
            {
            DRMLOG( _L("Is java file, do not delete"));
            retVal = EFalse;
            }
        else if( !common->ContentName().Right(4).CompareF(KSISExtension) )
            {
            DRMLOG( _L("Is an installation package, do not delete"));
            retVal = EFalse;
            }
        else
            {
            retVal = ETrue;
            }
        }
    CleanupStack::PopAndDestroy(); // rights

    DRMLOG( _L( "CDRMRightsDB::DeleteExpiredL <-" ) );

    return retVal;
    }


// -----------------------------------------------------------------------------
// CDRMRightsDB::GetUdtDataLC
// -----------------------------------------------------------------------------
//
HBufC8* CDRMRightsDB::GetUdtDataLC()
    {
#ifdef __DRM_OMA2
    HBufC8* udtData = HBufC8::NewMaxLC( KMaxUDTDataSize );
    TFileName backupFile;
    RFile input;
    TInt pos = KUdtDataPos;
    TPtr8 inRead( udtData->Des() );

#ifndef RD_MULTIPLE_DRIVE

    backupFile.Copy( KBackupDirectory );

#else //RD_MULTIPLE_DRIVE

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

    TFileName backupDir;
    backupDir.Format( KBackupDir, (TUint)driveLetter );

    backupFile.Copy( backupDir );

#endif

    backupFile.Append( KRightsDbBackupFile );

    // Open the udt file
    User::LeaveIfError( input.Open( iFileServer, backupFile, EFileRead ) );
    CleanupClosePushL( input );

    // Find the correct spot in the file
    User::LeaveIfError( input.Seek( ESeekStart, pos ) );

    // Read the data from the file
    User::LeaveIfError( input.Read( inRead, KMaxUDTDataSize ) );

    CleanupStack::PopAndDestroy(); // input
    return udtData;
 #else
    User::Leave(KErrNotSupported);
    return NULL;
 #endif
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::InitiateUdtL
// -----------------------------------------------------------------------------
//
#ifdef __DRM_OMA2
void CDRMRightsDB::InitiateUdtL( const TDesC8& aKey )
#else
void CDRMRightsDB::InitiateUdtL( const TDesC8& )
#endif // __DRM_OMA2
    {
#ifdef __DRM_OMA2
    TFileName backupFile;
    RFile input;
    HBufC8* keyData = NULL;

    MDrmKeyStorage* storage = DrmKeyStorageNewL();

    TCleanupItem storageCleanup( DeleteObject, storage );
    CleanupStack::PushL(storageCleanup);

    keyData = storage->RsaDecryptL( aKey );

    CleanupStack::PopAndDestroy();// storageCleanup
    CleanupStack::PushL( keyData );

#ifndef RD_MULTIPLE_DRIVE

    backupFile.Copy( KBackupDirectory );

#else //RD_MULTIPLE_DRIVE

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

    TFileName backupDir;
    backupDir.Format( KBackupDir, (TUint)driveLetter );

    backupFile.Copy( backupDir );

#endif

    backupFile.Append( KRightsDbBackupFile );

    // Open the udt file
    User::LeaveIfError( input.Open( iFileServer, backupFile, EFileRead ) );
    CleanupClosePushL( input );

    // Add the cleanup item to the cleanup stack
    TCleanupItem resetAndDestroy( CleanupData, reinterpret_cast<TAny*>(this) );
    CleanupStack::PushL( resetAndDestroy );

    // DEBUG DEBUG DEBUG: ignore the error
    TRAPD( error, RestoreContentFromFileL( input,
                             keyData->Right(KEncryptionKeySize),
                             KDRMUDTBackup ) );
    if( error )
        {
        // RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("InitiateUdtL: Restore failed\n\r"));
        User::Leave(error);
        }
    CleanupStack::PopAndDestroy( 3 ); // input, cleanup item, keyData
#else
    User::Leave(KErrNotSupported);
#endif // __DRM_OMA2
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::GetContentIDListL
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::GetContentIDListL( RPointerArray<HBufC8>& aArray )
    {
    HBufC8* contentId = NULL;

    for (TInt i = 0; i < 16; i++)
        {
        CDir* files = NULL;

        TFileName path = *iDbPath;

        path.Append(i < 10 ? i + '0' : i + 'a' - 10);
        path.Append('\\');

        if ( iFileServer.GetDir(path, KEntryAttDir, ESortNone, files) == KErrNone )
            {
            CleanupStack::PushL( files );

            for (TInt j = 0; j < files->Count(); j++)
                {
                TFileName tempPath( path );

                tempPath.Append((*files)[j].iName);

                TInt error = KErrNone;
                CDRMRightsData* rights = NULL;

                TRAP( error, rights = CDRMRightsData::OpenL( tempPath, iFileServer ) );
                if( rights )
                    {
                    CleanupStack::PushL( rights );
                    }
                else
                    {
                    if( error != KErrNotFound )
                        {
                        User::Leave( error );
                        }
                    continue;
                    }

                const CDRMCommonData* data = rights->GetCommonDataL();

                contentId = data->ContentID().AllocLC();
                aArray.AppendL( contentId );
                CleanupStack::Pop(); // contentId

                CleanupStack::PopAndDestroy(); // rights
                }

            CleanupStack::PopAndDestroy(); // files
            }
        }
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::WriteEncryptedStreamL
// The file will be opened and closed in CDRMBackup
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::WriteEncryptedStreamL( RWriteStream& aStream,
                                          const TDesC8& aMessageData,
                                          TDes8& aIv,
                                          TDes8& aRemainder,
                                          HBufC8*& aEncryptionBuffer,
                                          TInt& aBytesWritten )
    {
    TInt i = 0;
    TInt n = 0;
    TInt size = 0;
    TPtr8 ptr(aEncryptionBuffer->Des());
    TPtrC8 data;

    data.Set(aMessageData);
    if (aRemainder.Size() > 0 && aRemainder.Size() + data.Size() >= KEncryptionKeySize)
        {
        ptr.Copy(aRemainder);
        n = Min(KEncryptionKeySize - aRemainder.Size(), data.Size());
        ptr.Append(data.Left(n));

        EncryptL(aIv, ptr, EFalse);

        aStream.WriteL(ptr);
        aBytesWritten += ptr.Size();
        aIv.Copy(ptr.Right(KEncryptionKeySize));
        data.Set(data.Right(data.Size() - n));
        aRemainder.SetLength(0);
        }

    size = data.Size();
    for (i = 0; size > KEncryptionKeySize; i += KMaxEncryptionSize)
        {
        n = Min(KMaxEncryptionSize, ((size / KEncryptionKeySize)
                * KEncryptionKeySize));
        ptr.Copy(data.Mid(i, n));

        EncryptL(aIv, ptr, EFalse);

        aStream.WriteL(ptr);
        aBytesWritten += ptr.Size();
        aIv.Copy(ptr.Right(KEncryptionKeySize));
        size -= n;
        }
    aRemainder.Append(data.Right(size));
    }


// -----------------------------------------------------------------------------
// CDRMRightsDB::FinalizeEncryptedStreamL
// finalize the encryption
// -----------------------------------------------------------------------------
void CDRMRightsDB::FinalizeEncryptedStreamL( RWriteStream& aStream,
                                             TDes8& aIv,
                                             TDes8& aRemainder,
                                             HBufC8*& aEncryptionBuffer,
                                             TInt& aBytesWritten )
    {
    TPtr8 ptr(aEncryptionBuffer->Des());

    ptr.Copy(aRemainder);
    EncryptL(aIv, ptr, ETrue);
    aStream.WriteL(ptr);
    aStream.CommitL();
    aBytesWritten += ptr.Size();
    }


// -----------------------------------------------------------------------------
// CDRMRightsDB::BackupContentToFileL
// The file will be opened and closed in CDRMBackup
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::BackupContentToFileL( RFile& aBackupFile,
                                         const TDesC8& /* aEncryptionKey */,
                                         const TInt /* aMode */ )
    {
    //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("BackupContentToFileL\n\r"));
    // In UDT we need to check the mode
    TInt fileSize = 0;

    TUint permissions = 0;
    TUint8 continueMarker = 1;
    RFile copyHandle;
    TInt error = KErrNone;

    HBufC8* dataBuffer = NULL; // This is the buffer which gets reallocated
                               // if more space for data is required
                               // buf only if more space is needed, otherwise
                               // the size remains the same
                               // for start reserve as much as for the other buffer
                               // This is probably enough for all rights object
                               // But it's best to be sure

    TBuf8<KEncryptionKeySize> encIV;
    TBuf8<KEncryptionKeySize> remainder;
    HBufC8* encryptionBuffer = NULL; // The buffer used for the encryption in the middle
                                     // reserved only once
    TInt bytesWritten = 0;
    TPtr8 writeData(NULL,0,0);
    RMemWriteStream memStream;

    dataBuffer = HBufC8::NewLC( KMaxEncryptionSize );
    encryptionBuffer = HBufC8::NewLC( KMaxEncryptionSize );

    User::LeaveIfError( copyHandle.Duplicate(aBackupFile) );

    RFileWriteStream stream( copyHandle );
    CleanupClosePushL( stream );

    // first write the first 4 bytes empty, in the end the size is written there
    stream.WriteInt32L( fileSize );

#ifdef __DRM_OMA2
    AddUDTDataL( stream );
#endif

    encIV.SetLength(KEncryptionKeySize);
    // fill the iv with rnd data and write it to stream:
    MDrmKeyStorage* storage = DrmKeyStorageNewL();

    TCleanupItem storageCleanup( DeleteObject, storage );
    CleanupStack::PushL(storageCleanup);

    storage->RandomDataGetL(encIV,KEncryptionKeySize);
    CleanupStack::PopAndDestroy();//storageCleanup

    DRMLOG(_L("random encIV:"));
    DRMLOGHEX(encIV);


    stream.WriteL( encIV );

    // loop over all the rights objects and write them to the file

    for (TInt i = 0; i < 16; i++)
        {
        CDir* files = NULL;

        TFileName path = *iDbPath;

        path.Append(i < 10 ? i + '0' : i + 'a' - 10);
        path.Append('\\');

        if ( iFileServer.GetDir(path, KEntryAttDir, ESortNone, files) == KErrNone )
            {
            TInt j = 0;

            CleanupStack::PushL( files );

            for (j = 0; j < files->Count(); j++)
                {
                TFileName tempPath( path );
                CDRMPointerArray<CDRMPermission> *permissionArray = CDRMPointerArray<CDRMPermission>::NewLC();
                permissionArray->SetAutoCleanup( ETrue );

                tempPath.Append((*files)[j].iName);

                CDRMRightsData* rights = NULL;

                rights = CDRMRightsData::OpenLC( tempPath, iFileServer );

                // WRITE THE GENERIC DATA ABOUT THE OBJECT
                //-----------------------------------------------------------
                // First count the size we want to use:


                writeData.Set(&continueMarker,
                                sizeof(continueMarker),
                                sizeof(continueMarker));
                WriteEncryptedStreamL( stream,
                                       writeData,
                                       encIV,
                                       remainder,
                                       encryptionBuffer,
                                       bytesWritten );

                TInt sizeOfBuf = KEncryptionKeySize; // continue marker

                // Get the common data, Externalize it
                CDRMCommonData* data =
                  const_cast<CDRMCommonData*>(rights->GetCommonDataL());
                sizeOfBuf += data->Size();


                // Realloc if needed, probably wont be:
                if( sizeOfBuf > dataBuffer->Des().MaxSize() )
                    {
                    dataBuffer->ReAllocL( sizeOfBuf );
                    }

                // Write the size of the permission, used for decryption
                writeData.Set( reinterpret_cast<TUint8*>(&sizeOfBuf),
                               sizeof(sizeOfBuf),
                               sizeof(sizeOfBuf));

                WriteEncryptedStreamL( stream,
                                       writeData,
                                       encIV,
                                       remainder,
                                       encryptionBuffer,
                                       bytesWritten );


                memStream.Open( (TAny*)( dataBuffer->Ptr() ), sizeOfBuf );
                CleanupClosePushL( memStream );

                // The common data
                data->ExternalizeL( memStream );

                // The key
                // Get the key, Externalize it
                HBufC8* encKey = rights->GetKeyL();
                if( encKey == NULL )
                    {
                    encKey = HBufC8::NewMaxL(KEncryptionKeySize);
                    Mem::FillZ( const_cast<TUint8*>(encKey->Ptr()), KEncryptionKeySize);
                    }
                else
                    {
                    // Decrypt the key, the file is encrypted, it doesn't need to be twice
                    ModifyKey( *encKey );
                    }

                CleanupStack::PushL( encKey );

                memStream.WriteL( *encKey );
                CleanupStack::PopAndDestroy(); // enc key

                writeData.Set( const_cast<TUint8*>(dataBuffer->Ptr()),
                               sizeOfBuf, sizeOfBuf );

                WriteEncryptedStreamL( stream,
                                       writeData,
                                       encIV,
                                       remainder,
                                       encryptionBuffer,
                                       bytesWritten );


                CleanupStack::PopAndDestroy(); // memStream

                // Get the permissions and externalize their amount and them
                // If there are none ignore the error and just save the normal data
                TRAP(error, rights->FetchAllPermissionsL( *permissionArray ) );
                if( error )
                    {
                    if( !( error == KErrCANoRights || error == KErrCANoPermission ) )
                        {
                        User::LeaveIfError( error );
                        }
                    }

                // WRITE THE AMOUNT OF PERMISSIONS
                //-----------------------------------------------------------
                permissions = permissionArray->Count();

                writeData.Set(reinterpret_cast<TUint8*>(&permissions),
                              sizeof(permissions),
                              sizeof(permissions));

                WriteEncryptedStreamL( stream,
                                       writeData,
                                       encIV,
                                       remainder,
                                       encryptionBuffer,
                                       bytesWritten );

                for( TInt count = 0; count < permissions; count++ )
                    {
                    // WRITE EACH PERMISSION
                    //-----------------------------------------------------------
                    sizeOfBuf = (*permissionArray)[count]->Size();

                    // Realloc if needed, probably wont be:
                    if( sizeOfBuf > dataBuffer->Des().MaxSize() )
                        {
                        dataBuffer->ReAllocL( sizeOfBuf );
                        }

                    // Write the size of the permission, used for decryption
                    writeData.Set(reinterpret_cast<TUint8*>(&sizeOfBuf),
                                  sizeof(sizeOfBuf),
                                  sizeof(sizeOfBuf));

                    WriteEncryptedStreamL( stream,
                                           writeData,
                                           encIV,
                                           remainder,
                                           encryptionBuffer,
                                           bytesWritten );

                    // write the actual data
                    memStream.Open( (TAny*)( dataBuffer->Ptr() ), sizeOfBuf );
                    CleanupClosePushL( memStream );

                    (*permissionArray)[count]->ExternalizeL( memStream );

                    writeData.Set( const_cast<TUint8*>(dataBuffer->Ptr()),
                                   sizeOfBuf, sizeOfBuf );
                    WriteEncryptedStreamL( stream,
                                           writeData,
                                           encIV,
                                           remainder,
                                           encryptionBuffer,
                                           bytesWritten );

                    CleanupStack::PopAndDestroy();  // memstream

                    }
                CleanupStack::PopAndDestroy(2); // rights, permissionArray
                }

            CleanupStack::PopAndDestroy(); // files
            }
        }
    continueMarker = 0;
    writeData.Set(&continueMarker,
                  sizeof(continueMarker),
                  sizeof(continueMarker));
    WriteEncryptedStreamL( stream,
                           writeData,
                           encIV,
                           remainder,
                           encryptionBuffer,
                           bytesWritten );

    // Finalize the stream:
    FinalizeEncryptedStreamL( stream,
                              encIV,
                              remainder,
                              encryptionBuffer,
                              bytesWritten );

    CleanupStack::PopAndDestroy();// stream

    // Attach it to the file again, set the stream to the beginning

    User::LeaveIfError( copyHandle.Duplicate( aBackupFile ) );

    stream.Attach( copyHandle );
    CleanupClosePushL( stream );

    aBackupFile.Size( fileSize );

    // write the size of the file including the 4 bytes in the start
    stream.WriteInt32L( fileSize );

    CleanupStack::PopAndDestroy(3); // stream, databuffer, encryptionbuffer
    // DEBUG
    // Perform restore:
    // RestoreContentFromFileL( aBackupFile, *iKey, 0 );
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::RestoreContentFromFileL
// The file will be opened and closed in CDRMBackup
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::RestoreContentFromFileL( RFile& aBackupFile,
                                            const TDesC8& aEncryptionKey,
                                            const TInt aMode )
    {
    // RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("RestoreContentFromFileL\n\r"));
    TInt8 continueMarker = 1;
    TBuf8<16> key;
    TBuf8<16> encryptionKey;
    TInt permissions = 0;
    CDRMPermission* permission = CDRMPermission::NewLC();
    CDRMCommonData *commonData = NULL;
    CDRMPointerArray<CDRMPermission> *permissionArray = CDRMPointerArray<CDRMPermission>::NewLC();
    permissionArray->SetAutoCleanup( ETrue );
    TDRMUniqueID uniqueID = 0;
    RFile fileHandle;
    TInt readPos = 0;
    TInt size = 0;
    TInt dataLeft = 0;
    TPtr8 keyData(NULL,0,0);

    // maintain knowledge about stateful rights not being restored
    TBool stateful = EFalse;


    DRMLOG( _L( "CDRMRightsDB::RestoreContentFromFileL ->" ) );

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();

    key.SetLength( KEncryptionKeySize );
    fileHandle.Duplicate( aBackupFile );
    CleanupClosePushL( fileHandle );

    HBufC8* dataBuffer = NULL; // This is the buffer which gets reallocated
                               // if more space for data is required
                               // buf only if more space is needed, otherwise
                               // the size remains the same
                               // for start reserve as much as for the other buffer
                               // This is probably enough for all rights object
                               // But it's best to be sure

    TBuf8<KEncryptionKeySize> encIV;

    TPtr8 readData(NULL,0,0);

    switch( aMode )
        {
        case KDRMNormalBackup:
            {
            encryptionKey.Copy( *iKey );
            }
            break;
        case KDRMUDTBackup:
            {
            encryptionKey.Copy(aEncryptionKey);
            }
            break;
        default:
            User::Leave( KErrArgument );
        }

    encryptionKey.SetLength(KEncryptionKeySize);


    dataBuffer = HBufC8::NewLC( KMaxEncryptionSize );

    encIV.SetLength( KEncryptionKeySize );

    // Check that the decryption works, if it doesn't then the
    // key is faulty
    User::LeaveIfError( aBackupFile.Size( readPos ) );
    if( readPos < KUdtDataPos+KMaxUDTDataSize+(KEncryptionKeySize*2) )
        {
          // RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("RestoreContentFromFileL : corrupt\n\r"));
        User::Leave(KErrCorrupt);
        }
    readPos -= KEncryptionKeySize*2;

    User::LeaveIfError( fileHandle.Seek( ESeekStart, readPos ) );

    // Read the IV
    readData.Set( const_cast<TUint8*>(encIV.Ptr()), 0, KEncryptionKeySize );
    User::LeaveIfError( fileHandle.Read( readData, KEncryptionKeySize ) );

    // Read the data:
    readData.Set( const_cast<TUint8*>( dataBuffer->Ptr()), 0,
                  KEncryptionKeySize );
    User::LeaveIfError( fileHandle.Read( readData, KEncryptionKeySize ) );

    DecryptL( encIV, readData, EFalse, encryptionKey );

    // Check if the padding matches, if not the function will leave
    CheckPaddingL( readData );

    // End checking

    // Now we are ready to go through the file
    //-----------------------------------------------------------------------

    // Duplicate file handle
    readPos = KUdtDataPos+KMaxUDTDataSize;
    User::LeaveIfError( fileHandle.Seek( ESeekStart, readPos ) );
    iMemStream.Close();

    ReadDataL( fileHandle, encIV, readData, dataBuffer,
               dataLeft, size, ETrue, encryptionKey );

    iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);

    // Read data now contains decrypted data which we can go through

    // loop over all the rights objects and merge them to the db
    while( true )
        {
        keyData.Set(const_cast<TUint8*>(key.Ptr()), 0, KEncryptionKeySize);

        if( dataLeft < 1 )
            {
            size = 1;
            iMemStream.Close();
            ReadDataL( fileHandle, encIV, readData, dataBuffer,
                       dataLeft, size, EFalse, encryptionKey );
            iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
            }

        continueMarker = iMemStream.ReadInt8L();
        dataLeft -= 1;

        if( !continueMarker  )
            {
            // RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("RestoreContentFromFileL : exit from loop\n\r"));
            break;
            }

         if( dataLeft < 4 )
            {
            size = 4;
            iMemStream.Close();
            ReadDataL( fileHandle, encIV, readData, dataBuffer,
                       dataLeft, size, EFalse, encryptionKey );
            iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
            }

        // Read the size of the data:
        size = iMemStream.ReadInt32L();
        dataLeft -= 4;

        if( size > dataLeft )
            {
            iMemStream.Close();
            ReadDataL( fileHandle, encIV, readData, dataBuffer,
                       dataLeft, size, EFalse, encryptionKey );
            iMemStream.Open( const_cast<TUint8*>( readData.Ptr()),dataLeft);
            }

        // Read the common data:
        commonData = CDRMCommonData::NewLC();
        commonData->InternalizeL(iMemStream);

        // Read the content encryption key
        iMemStream.ReadL( keyData, KEncryptionKeySize );
        dataLeft -= size;

        if( dataLeft < 4 )
            {
            size = 4;
            iMemStream.Close();
            ReadDataL( fileHandle, encIV, readData, dataBuffer,
                       dataLeft, size, EFalse, encryptionKey );
            iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
            }

        // read the amount of permissions
        permissions = iMemStream.ReadInt32L();
        dataLeft -= 4;


        // Create the entry if needed
        TFileName path;
        TInt error = KErrNone;
        CDRMRightsData* rights = NULL;
        TBuf8<16> nullDesc;
        TBuf<16> nullDesc2;
        HBufC8* oldKey = NULL;
        TInt8 insertPerm = 1;
        TBool doInsert = ETrue;
        TBool keyExists = EFalse;

        for( TInt counter = 0; counter < KEncryptionKeySize; counter++ )
            {
            if( key[counter] != 0x00 )
                {
                keyExists = ETrue;
                counter = KEncryptionKeySize;
                }
            }


        // Encrypt the key
        if( keyExists )
            {
            ModifyKey( key );
            }

        GetRightsFileNameL( commonData->ContentID(), path);

        // Indicate that the DB is updated
        iLastUpdate.HomeTime();

        TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );

        if( error == KErrNotFound )
            {
            // Indicate that the DB is updated
            iLastUpdate.HomeTime();

            if( keyExists )
                {
                TRAP(error, rights = CDRMRightsData::NewL( commonData, key, path, iFileServer ) );
                }
            else
                {
                TRAP(error, rights = CDRMRightsData::NewL( commonData, KNullDesC8, path, iFileServer ) );
                }

            CleanupStack::Pop(); // Pop Common Data
            CleanupStack::PushL(rights); // Push the rights in:
            insertPerm = -1;
            }
        else
            {
            // Destroy common data if it already exits per OpenL
            CleanupStack::PopAndDestroy();

            // Leave if another error occurred
            User::LeaveIfError( error );

            if( rights )
                {
                CleanupStack::PushL( rights );
                oldKey = rights->GetKeyL();

                // if there is no key and there is one in the new one
                if( !oldKey && keyExists )
                    {
                    insertPerm = 0;
                    }
                else if( oldKey && key.Compare( *oldKey ) ) // If the key is different
                    {
                    insertPerm = 0;
                    }
                if( oldKey )
                    {
                    delete oldKey;
                    }
                }
            }

        if( !rights )
            {
            User::Leave( KErrGeneral );
            }




        if( insertPerm == -1 ) // Add everything no checks needed
            {
            for( TInt count = 0; count < permissions; count++ )
                {
                if( dataLeft < 4 )
                    {
                    size = 4;
                    iMemStream.Close();
                    ReadDataL( fileHandle, encIV, readData, dataBuffer,
                               dataLeft, size, EFalse, encryptionKey );
                    iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
                    }

                // Read the size of the data:
                size = iMemStream.ReadInt32L();
                dataLeft -= 4;

                if( size > dataLeft )
                    {
                    iMemStream.Close();
                    ReadDataL( fileHandle, encIV, readData, dataBuffer,
                               dataLeft, size, EFalse, encryptionKey );
                    iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
                    }

                permission->InternalizeL( iMemStream );
                dataLeft -= size;

                if( !permission->Stateful() || aMode == KDRMUDTBackup )
                    {
                    rights->StoreNewPermissionL( *permission, uniqueID );
                    }
                else if( !stateful )
                    {
                    stateful = ETrue;
                    }
                }
            }
        else if( insertPerm == 1) // Add stuff that doesn't match the times
            {
            // Indicate that the DB is updated
            iLastUpdate.HomeTime();

            // If there are no rights that's an ok thing
            // Fix memory handling
            TRAP( error, rights->FetchAllPermissionsL( *permissionArray ) );
            if( error )
                {
                if( !( error == KErrCANoRights ||
                       error == KErrCANoPermission ) )
                    {
                    User::LeaveIfError(error);
                    }

                }


            for( TInt count = 0; count < permissions; count++ )
                {
                if( dataLeft < 4 )
                    {
                    size = 4;
                    iMemStream.Close();
                    ReadDataL( fileHandle, encIV, readData, dataBuffer,
                               dataLeft, size, EFalse, encryptionKey );
                    iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
                    }

                // Read the size of the data:
                size = iMemStream.ReadInt32L();
                dataLeft -= 4;

                if( size > dataLeft )
                    {
                    iMemStream.Close();
                    ReadDataL( fileHandle, encIV, readData, dataBuffer,
                               dataLeft, size, EFalse, encryptionKey );
                    iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
                    }

                permission->InternalizeL( iMemStream );
                dataLeft -= size;

                doInsert = ETrue;

                for( TInt perm = 0; perm < permissionArray->Count(); perm++)
                    {
                    if( (*permissionArray)[perm]->iOriginalInsertTime ==
                        permission->iOriginalInsertTime )
                        {
                        doInsert = EFalse;
                        break;
                        }
                    }

                if( doInsert && (!permission->Stateful() || aMode == KDRMUDTBackup ) )
                    {
                    rights->StoreNewPermissionL( *permission, uniqueID );
                    }
                else if( doInsert && !stateful )
                    {
                    stateful = ETrue;
                    }
                }
                permissionArray->ResetAndDestroy();
            }
        else  // Just read it all but dont add anything
            {
            // Indicate that the DB is updated
            iLastUpdate.HomeTime();

            for( TInt count = 0; count < permissions; count++ )
                {
                if( dataLeft < 4 )
                    {
                    size = 4;
                    iMemStream.Close();
                    ReadDataL( fileHandle, encIV, readData, dataBuffer,
                               dataLeft, size, EFalse, encryptionKey );
                    iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);
                    }

                // Read the size of the data:
                size = iMemStream.ReadInt32L();
                dataLeft -= 4;

                if( size > dataLeft )
                    {
                    iMemStream.Close();
                    ReadDataL( fileHandle, encIV, readData, dataBuffer,
                               dataLeft, size, EFalse, encryptionKey );
                    iMemStream.Open( const_cast<TUint8*>( readData.Ptr()), dataLeft);

                    }

                permission->InternalizeL( iMemStream );
                dataLeft -= size;
                }
            }
        CleanupStack::PopAndDestroy(); // rights
        }
    iMemStream.Close();
    CleanupStack::PopAndDestroy( 4 ); // permission, permissionArray, fileHandle, dataBuffer

    DRMLOG( _L( "CDRMRightsDB::RestoreContentFromFileL ->" ) );

    // If there are stateful rights not put to the phone, this is always EFalse for
    // the UDT case leave with the special error case to leave the restored database
    // to enable UDT
    if( stateful )
        {
        User::Leave( KErrPermissionDenied );
        }
    };



// -----------------------------------------------------------------------------
// CDRMRightsDB::HashContentID
// removed the cid: or flk: from the beginning of the content ID before hashing
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::HashContentID( TPtrC8& aHashKey, const TDesC8& aContentID )
    {
    TPtrC8 cid;
    iHasher->Reset();

    if ( !aContentID.Left( KFLKStringLength ).Compare( KFLKString ) )
        {
        cid.Set( aContentID.Right( aContentID.Length()-KCIDStringLength ) );
        }
    else if ( !aContentID.Left( KCIDStringLength ).Compare( KCIDString ) )
        {
        cid.Set( aContentID.Right( aContentID.Length()-KCIDStringLength ) );
        }
    else
        {
        cid.Set( aContentID );
        }

    aHashKey.Set( iHasher->Hash( cid ) );
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::GetRightsFileNameL
//
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::GetRightsFileNameL(
    const TDesC8& aContentID,
    TFileName& aPath)
    {
    TPtrC8 hash;
    TInt i;
    TInt v;

    aPath.Copy(*iDbPath);
    HashContentID(hash, aContentID);
    v = hash[0] >> 4;
    aPath.Append(v < 10 ? v + '0' : v + 'a' - 10);
    aPath.Append('\\');
    for (i = 0; i < hash.Length(); i++)
        {
        v = hash[i] >> 4;
        aPath.Append(v < 10 ? v + '0' : v + 'a' - 10);
        v = hash[i] & 0x0f;
        aPath.Append(v < 10 ? v + '0' : v + 'a' - 10);
        }
    aPath.Append(KROExtension);
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::GetXMLFileNameL
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::GetXMLFileNameL(
    const TDesC8& aRoID,
    TFileName& aPath)
    {
    TPtrC8 hash;
    TInt i;
    TInt v;

    aPath.Copy(*iDbPath);
    HashContentID(hash, aRoID);
    aPath.Append(KRODirName);
    for (i = 0; i < hash.Length(); i++)
        {
        v = hash[i] >> 4;
        aPath.Append(v < 10 ? v + '0' : v + 'a' - 10);
        v = hash[i] & 0x0f;
        aPath.Append(v < 10 ? v + '0' : v + 'a' - 10);
        }
    aPath.Append(KXmlExtension);
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::InitializeDatabaseL
// initializes the database for use, called before every external interface
// function ( not NewL, NewLC )
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::InitializeDatabaseL(void)
    {
    TInt i;
    TFileName path;

    DRMLOG( _L( "CDRMRightsDB::InitializeDatabaseL ->" ) );

    iFileServer.MkDirAll(*iDbPath);
    for (i = 0; i < 16; i++)
        {
        // Indicate that the DB is updated
        iLastUpdate.HomeTime();

        path.Copy(*iDbPath);
        path.Append(i < 10 ? i + '0' : i + 'a' - 10);
        path.Append('\\');
        iFileServer.MkDir(path);
        }

    // Indicate that the DB is updated
    iLastUpdate.HomeTime();

    // Domain RO XML dir
    path.Copy(*iDbPath);
    path.Append(KRODirName);
    iFileServer.MkDirAll(path);

    DRMLOG( _L( "CDRMRightsDB::InitializeDatabaseL <-" ) );
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::GetXMLFileNameL
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::ModifyKey( TDesC8& aKey )
    {
    TInt* ptrOriginal = NULL;
    TInt* ptrCryptKey = NULL;

    // Cast into TInt pointers
    ptrOriginal = reinterpret_cast<TInt*>( const_cast<TUint8*>( aKey.Ptr() ) );
    ptrCryptKey = reinterpret_cast<TInt*>( const_cast<TUint8*>( iKey->Ptr() ) );

    // XOR the key with the DB key
    ptrOriginal[0] ^= ptrCryptKey[0];
    ptrOriginal[1] ^= ptrCryptKey[1];
    ptrOriginal[2] ^= ptrCryptKey[2];
    ptrOriginal[3] ^= ptrCryptKey[3];
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::AddUDTDataL
// EB = 00 || BT || PS || 00 || D
// -----------------------------------------------------------------------------
//
#ifdef __DRM_OMA2
void CDRMRightsDB::AddUDTDataL( RWriteStream& aStream )
#else
void CDRMRightsDB::AddUDTDataL( RWriteStream& )
#endif // __DRM_OMA2
    {
#ifdef __DRM_OMA2
    TBuf8<MDrmKeyStorage::KRdbSerialNumberLength> serialNumber;
    TBuf8<KMaxUDTDataSize> buffer;
    TUint8* ptr = const_cast<TUint8*>(buffer.Ptr());
    HBufC8* result = NULL;
    TPtr8 udtData( ptr+KDeviceDataBlock, KDeviceDataBlock, KDeviceDataBlock );
    HBufC8* phoneSerialNumber = NULL;
    TInt pos = 0;

    MDrmKeyStorage* storage = DrmKeyStorageNewL();
    TCleanupItem storageCleanup( DeleteObject, storage );
    CleanupStack::PushL(storageCleanup);

    storage->GetRdbSerialNumberL( serialNumber );

    // Fill the descriptor with random data

    TPtr8 random( const_cast<TUint8*>(buffer.Ptr()),
                  KMaxUDTDataSize,
                  KMaxUDTDataSize );

    storage->RandomDataGetL(random,KMaxUDTDataSize);

    DRMLOG(_L("random UDTData:"));
    DRMLOGHEX(buffer);

    // Get the serial number:
    phoneSerialNumber = CnvUtfConverter::ConvertFromUnicodeToUtf8L( *iImei );
    CleanupStack::PushL( phoneSerialNumber );

    // Device public key encrypted Rights Database Serial Number 128 bytes
    // Device public key encrypted Rights Database Encryption Key 128 bytes
    // ----------------------------------------------------------
    // 00 || 02 || padding || 00 || 16bytes || 16 bytes

    // Construct the 128 bit buffer
    ptr = const_cast<TUint8*>(udtData.Ptr());

    // Set the first byte to 0
    // Set the padding type as random padding
    ptr[0] = 0x00;
    ptr[1] = 0x02;

    pos = KDeviceDataBlock;
    pos -= KEncryptionKeySize;

    // insert the key
    udtData.Replace( pos, KEncryptionKeySize, *iKey );

    pos -= MDrmKeyStorage::KRdbSerialNumberLength;

    // insert the db serial number
    udtData.Replace( pos, MDrmKeyStorage::KRdbSerialNumberLength, serialNumber );

    // insert the finish padding block
    pos = pos - 1;
    ptr[pos] = 0x00;

    result = storage->RsaSignL( udtData );
    CleanupStack::PushL( result );

    // Write the data to the stream
    aStream.WriteL( *result, KDeviceDataBlock );

    CleanupStack::PopAndDestroy(); // result

    // Device public key encrypted Device serial number 128 bytes
    // ----------------------------------------------------------
    // 00 || 02 || padding || 00 || Size || Imei

    // Construct the 128 bit buffer
    ptr = const_cast<TUint8*>(buffer.Ptr());
    udtData.Set( ptr, KDeviceDataBlock, KDeviceDataBlock );
    ptr = const_cast<TUint8*>(udtData.Ptr());

    // Set the first byte to 0
    // Set the padding type as random padding
    ptr[0] = 0x00;
    ptr[1] = 0x02;

    pos = KDeviceDataBlock;
    pos -= phoneSerialNumber->Length();

    // insert the phone serial number

    udtData.Replace( pos, phoneSerialNumber->Length(), *phoneSerialNumber );

    pos -= 1;

    // insert the db serial number
    ptr[pos] = phoneSerialNumber->Length();

    // insert the finish padding block
    pos -= 1;
    ptr[pos] = 0x00;

    result = storage->RsaSignL( udtData );
    CleanupStack::PushL( result );

    // Write the data to the stream
    aStream.WriteL( *result, KDeviceDataBlock );

    CleanupStack::PopAndDestroy(); // result

    ptr = const_cast<TUint8*>(buffer.Ptr());

    // UDT public key encrypted Rights Database Serial Number 256 bytes
    // UDT public key encrypted Rights Database Encryption Key 256 bytes
    // ----------------------------------------------------------
    // 00 || 02 || padding || 00 || Size || Imei || 16bytes || 16 bytes

    // Fill the descriptor with random data
    storage->RandomDataGetL(random,KMaxUDTDataSize);

    DRMLOG(_L("random UDTData:"));
    DRMLOGHEX(buffer);

    // Make the beginning of the buffer correct for use:
    ptr = const_cast<TUint8*>(buffer.Ptr());
    udtData.Set( ptr, KMaxUDTDataSize, KMaxUDTDataSize );
    ptr[0] = 0x00;
    ptr[1] = 0x02;

    pos = KMaxUDTDataSize;
    pos -= KEncryptionKeySize;

    // insert the key
    udtData.Replace( pos, KEncryptionKeySize, *iKey );

    pos -= MDrmKeyStorage::KRdbSerialNumberLength;

    // insert the db serial number
    udtData.Replace( pos, MDrmKeyStorage::KRdbSerialNumberLength, serialNumber );

    // insert the phone serial number
    pos -= phoneSerialNumber->Length();
    udtData.Replace( pos, phoneSerialNumber->Length(), *phoneSerialNumber );

    pos -= 4;

    // insert the size of the phoneSerialNumber field
    WriteIntToBlock( phoneSerialNumber->Length(), udtData, pos );

    // insert the finish padding block
    pos -= 1;
    ptr[pos] = 0x00;
    TInt error = KErrNone;

    TPtrC8 createData( udtData.Mid(pos+1));

    TRAP( error, result = storage->UdtEncryptL( createData ));
    // No udt certificate write the block but empty
    if( error )
        {
        result = HBufC8::NewMaxL( 256 );
        Mem::FillZ( const_cast<TUint8*>(result->Ptr()), 256);
        }
    CleanupStack::PushL( result );

    aStream.WriteL( *result, 256 );

    CleanupStack::PopAndDestroy(3); //result,phoneSerialNumber, storageCleanup
#else
    User::Leave(KErrNotSupported);
#endif
    };

// test function
void CDRMRightsDB::CreateDummyUDTFileL()
    {
#ifdef __DRM_OMA2
    TFileName backupFile;
    RFile input;
    TInt fileSize = 4 + 256 + 256;

    backupFile.Copy( _L("c:\\") );
    backupFile.Append( KRightsDbBackupFile );

    // Open the udt file
    User::LeaveIfError( input.Replace( iFileServer, backupFile, EFileRead|EFileWrite ) );
    RFileWriteStream stream( input, 0);

    stream.WriteInt32L( fileSize );
    CleanupClosePushL(stream);

    AddUDTDataL( stream );
    CleanupStack::PopAndDestroy();
#else
    User::Leave(KErrNotSupported);
#endif // __DRM_OMA2
    };


// -----------------------------------------------------------------------------
// CDRMRightsDB::CleanUdtData
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::CleanUdtData()
    {
#ifdef __DRM_OMA2
    TFileName backupFile;

#ifndef RD_MULTIPLE_DRIVE

    backupFile.Copy( KBackupDirectory );

#else //RD_MULTIPLE_DRIVE

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

    TFileName backupDir;
    backupDir.Format( KBackupDir, (TUint)driveLetter );

    backupFile.Copy( backupDir );

#endif

    backupFile.Append( KRightsDbBackupFile );

    // Open the udt file
    iFileServer.Delete( backupFile );
#endif // __DRM_OMA2
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::EncryptL
//
// -----------------------------------------------------------------------------
//     // iRdb.Encrypt(aIv, ptr, ETrue);
void CDRMRightsDB::EncryptL( const TDesC8& aIv,
                             TPtr8& aData,
                             TBool aAddPadding )
    {
    CAESEncryptor* aes = NULL;
    CModeCBCEncryptor* cbc = NULL;
    TInt i;
    TInt lastBlockStart;
    TInt dataLength;
    TInt padding;
    TPtr8 d(NULL, 0);

    aes = CAESEncryptor::NewLC(*iKey);
    cbc = CModeCBCEncryptor::NewL(aes, aIv);
    CleanupStack::Pop(); // aes, now owned by cbc
    CleanupStack::PushL(cbc);

    dataLength = aData.Length();
    lastBlockStart = (dataLength / KEncryptionKeySize) * KEncryptionKeySize;
    for (i = 0; i < lastBlockStart; i += KEncryptionKeySize)
        {
        d.Set(aData.MidTPtr (i, KEncryptionKeySize));
        cbc->Transform(d);
        }

    if (aAddPadding)
        {
        padding = KEncryptionKeySize - (dataLength - lastBlockStart);
        aData.SetLength(lastBlockStart + KEncryptionKeySize);
        for (i = dataLength; i < lastBlockStart + KEncryptionKeySize; i++)
            {
            aData[i] = padding;
            }
        d.Set(aData.MidTPtr (lastBlockStart, KEncryptionKeySize));
        cbc->Transform(d);
        }
    CleanupStack::PopAndDestroy(); // cbc
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::DecryptL
// Decrypt data and return it to the caller, using the CEK for this session
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::DecryptL( const TDesC8& aIv,
                             TPtr8& aData,
                             TBool aRemovePadding,
                             const TDesC8& aEncryptionKey )
    {
    CAESDecryptor* aes = NULL;
    CModeCBCDecryptor* cbc = NULL;
    TInt i;
    TInt n;
    TPtr8 d(NULL, 0);

    if (iKey->Length() > 0)
        {
        aes = CAESDecryptor::NewLC( aEncryptionKey );
        cbc = CModeCBCDecryptor::NewLC(aes, aIv);
        CleanupStack::Pop(); // aes, now owned by cbc

        for (i = 0; i < aData.Length(); i += KEncryptionKeySize )
            {
            d.Set(aData.MidTPtr (i, KEncryptionKeySize));
            cbc->Transform(d);
            }
        if (aRemovePadding)
            {
            n = aData.Length();
            aData.SetLength(n - aData[n - 1]);
            }
        CleanupStack::PopAndDestroy(); // cbc
        }
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::CheckPaddingL
// Check if the padding matches, aka if they key used for decryption was
// incorrect leave with KErrPermissionDenied
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::CheckPaddingL( const TDesC8& aData )
    {
    TUint8 character = 0;
    TInt limiter = 0;

    for( TInt i = 15; i >= limiter; i-- )
        {
        if( i == 15 )
            {
            character = aData[i];
            if( character < 1 || character > 16 )
                {
                User::Leave( KErrPermissionDenied );
                }
            limiter = 16 - character;
            }
        if( aData[i] != character )
            {
            User::Leave( KErrPermissionDenied );
            }
        }
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::ReadDataL
// Read Data from the file, if it doesn't have enough leave
// Error handling missing
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::ReadDataL( RFile& aStream,
                              TDes8& aEncIV,
                              TPtr8& aReadData,
                              HBufC8*& aDataBuffer,
                              TInt& aDataLeft,
                              TInt aSize,
                              TBool aStart,
                              const TDesC8& aEncryptionKey )
    {
    TPtr8 readData(NULL, 0, 0);
    HBufC8 *newBuffer = 0;
    TInt bufferSize = 0;
    TInt pos = 0;
    TUint8* currPtr = const_cast<TUint8*>(aDataBuffer->Ptr()) + aDataBuffer->Des().MaxSize();
    currPtr -= aDataLeft;
    currPtr -= KEncryptionKeySize;
    TInt checknum = 0;

    // In the beginning read IV from the stream                             1
    //------------------------------------------------------------------------
    if( aStart )
        {
        readData.Set( const_cast<TUint8*>(aEncIV.Ptr()), 0, KEncryptionKeySize );
        User::LeaveIfError(aStream.Read( readData, KEncryptionKeySize ));
        }
    else
        {
        bufferSize = aDataBuffer->Des().MaxLength()-KEncryptionKeySize;
        // Copy the old IV to the new IV
        Mem::Copy( const_cast<TUint8*>( aEncIV.Ptr() ),
                   const_cast<TUint8*>( aDataBuffer->Ptr() ) +
                   bufferSize,
                   KEncryptionKeySize );
        }


    // If the block is too small realloc:                                   2
    //------------------------------------------------------------------------
    bufferSize = aDataBuffer->Des().MaxLength()-KEncryptionKeySize;

    if( aSize > bufferSize)
        {
        bufferSize = aSize / KEncryptionKeySize;
        bufferSize *= KEncryptionKeySize;
        bufferSize += 2 * KEncryptionKeySize;
        newBuffer = HBufC8::NewLC( bufferSize );
        }

    // calculate a proper amount of data to copy so that
    // we stay in increments of 16                                          3
    //------------------------------------------------------------------------
    pos = aDataLeft;

    if( aDataLeft % KEncryptionKeySize )
        {
        pos = pos - ( pos % KEncryptionKeySize ) + KEncryptionKeySize;
        }


    // Copy the existing data into the buffer                               4
    //------------------------------------------------------------------------
    if( !newBuffer )
        {
        Mem::Copy( const_cast<TUint8*>( aDataBuffer->Ptr() ),
                   const_cast<TUint8*>( aDataBuffer->Ptr() ) +
                   ( aDataBuffer->Des().MaxLength()-KEncryptionKeySize - pos ),
                   pos );
        }
    else
        {
        Mem::Copy( const_cast<TUint8*>( newBuffer->Ptr() ),
                   const_cast<TUint8*>( aDataBuffer->Ptr() ) +
                   ( aDataBuffer->Des().MaxLength()-KEncryptionKeySize - pos ),
                   pos );
        delete aDataBuffer;
        aDataBuffer = newBuffer;
        }

    // Read the new data from the file                                      5
    //------------------------------------------------------------------------
    readData.Set( const_cast<TUint8*>( aDataBuffer->Ptr() ) + pos, 0,
              aDataBuffer->Des().MaxLength()-KEncryptionKeySize - pos  );

/*    readData.Set( aDataBuffer->Des().
             MidTPtr( pos,
                      aDataBuffer->Des().MaxLength() -
                        KEncryptionKeySize -
                        pos ) );
*/
    checknum = aStream.Read( readData );
    User::LeaveIfError( checknum );

    checknum = readData.Length();
    checknum = pos + readData.Length();
    checknum = aDataBuffer->Des().MaxLength();
    checknum = aDataBuffer->Des().MaxLength()-KEncryptionKeySize;

    // Check if we are at the final part                                    6
    //------------------------------------------------------------------------
    if( pos + readData.Length() !=
        aDataBuffer->Des().MaxLength()-KEncryptionKeySize )
        {
        DecryptL( aEncIV, readData, ETrue, aEncryptionKey );
        Mem::FillZ( const_cast<TUint8*>( aEncIV.Ptr() ), KEncryptionKeySize );
        }
    else
        {
        Mem::Copy( const_cast<TUint8*>( aDataBuffer->Ptr() ) +
                   aDataBuffer->Des().MaxLength()-KEncryptionKeySize,
                   const_cast<TUint8*>( aDataBuffer->Ptr() ) +
                   aDataBuffer->Des().MaxLength()-(KEncryptionKeySize*2),
                   KEncryptionKeySize );


        DecryptL( aEncIV, readData, EFalse, aEncryptionKey );

        }

    // Set the buffer you read from to this:
    aReadData.Set( const_cast<TUint8*>(aDataBuffer->Ptr()) + pos-aDataLeft,
                   readData.Length()+aDataLeft,
                   readData.Length()+aDataLeft);

    // Set the data length
    aDataLeft = aReadData.Length();
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::SetAuthenticationSeedL
// Set the seed in the common data
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::SetAuthenticationSeedL( const TDesC8& aContentId,
                                           const TDesC8& aSeed )
    {
    TFileName path;
    TInt error = KErrNone;
    CDRMRightsData* rights = NULL;
    CDRMCommonData* data = NULL;

    GetRightsFileNameL( aContentId, path);

    TRAP( error, rights = CDRMRightsData::OpenL( path, iFileServer ) );
    if( rights )
        {
        CleanupStack::PushL( rights );
        }
    else
        {
        User::Leave( error );
        }

    data = const_cast<CDRMCommonData*>(rights->GetCommonDataL());

    data->SetAuthenticationSeedL( aSeed );

    rights->UpdateCommonDataL( data );

    CleanupStack::PopAndDestroy(); // rights
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::GetAuthenticationSeedL
// Get the seed from the common data
// -----------------------------------------------------------------------------
//
HBufC8* CDRMRightsDB::GetAuthenticationSeedL( const TDesC8& aContentId )
    {
    TFileName path;
    CDRMRightsData* rights( NULL );
    HBufC8* seed( NULL );

    GetRightsFileNameL( aContentId, path );

    rights = CDRMRightsData::OpenL( path, iFileServer );
    CleanupStack::PushL( rights );

    seed = const_cast< CDRMCommonData* >( rights->GetCommonDataL() )
            ->AuthenticationSeed().AllocL();

    CleanupStack::PopAndDestroy(); // rights

    return seed;
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::Updating
// Return the iLastUpdate flag. Updating is considered as something that happens
// in a specific time window, to acknowledge the fact that e.g. events which are
// tiggered in the updating process come a bit later through the active
// scheduled.
// -----------------------------------------------------------------------------
//
TBool CDRMRightsDB::Updating()
    {
    TTime now;
    TBool r = EFalse;
    TTimeIntervalMicroSeconds interval;

    now.HomeTime();
    interval = now.MicroSecondsFrom( iLastUpdate );

#ifdef _LOGGING
    TBuf<256> logBuffer;
    logBuffer.AppendNum( interval.Int64() );
    DRMLOG( _L(" CDRMRightsDB::Updating: Update interval: " ) );
    DRMLOG( logBuffer );
#endif

    if ( interval < KMaxUpdateTime )
        {
        r = ETrue;
        }
    return r;
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::MarkAsCorrupted
// Mark the DB as corrupted by creating a specific file in the RDB structure. If
// that file is detected, the RDB gets recreated.
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::MarkAsCorrupted()
    {
    TFileName name;
    RFile file;

    name.Copy( *iDbPath );
    name.Append( KCorruptionFlagFile );
    file.Create( iFileServer, name, EFileWrite );
    file.Close();
    }

// -----------------------------------------------------------------------------
// CDRMRightsDB::CheckCleanup
// Delete the db file if it's possible
// -----------------------------------------------------------------------------
//
void CDRMRightsDB::CheckCleanup( const TDesC& aFileName )
    {
    TInt canDelete = 0;
    TInt error = KErrNone;

    TRAP(error, canDelete = DeleteExpiredL( aFileName, Time::NullTTime()));

    if( !error && canDelete )
        {
        DRMLOG(_L("File empty, deletion allowed, deleting it:"));
        DRMLOG( aFileName );
        iFileServer.Delete( aFileName );
        }
    }


//  End of File