omadrm/drmengine/server/src/drmrightsdb.cpp
changeset 0 95b198f216e5
child 18 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/server/src/drmrightsdb.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,2784 @@
+/*
+* 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