omadrm/drmengine/dcfrepository/server/src/DcfRepSrv.cpp
author hgs
Thu, 14 Oct 2010 13:45:23 +0300
changeset 84 b09186059647
parent 23 493788a4a8a4
permissions -rw-r--r--
201039_02

/*
* Copyright (c) 2002-2010 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:  server implementation
*
*/


// INCLUDE FILES
#include    "DcfRepSrv.h"
#include    "DcfRepSrvSes.h"
#include    "DcfRepCommon.h"
#include    "Pair.h"
#include    "FileScan.h"
#include    <e32std.h>
#include    <e32base.h>
#include    <f32file.h>
#include    <caf/data.h>
#include    <caf/content.h>
#include    <Oma2Agent.h> // oma2agent
#include    "oma2dcf.h"
#include    "Oma1Dcf.h"
#include    "drmlog.h"
#include <starterclient.h>

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

// EXTERNAL DATA STRUCTURES
// EXTERNAL FUNCTION PROTOTYPES
// CONSTANTS
_LIT(KSqlUpdate1 , "select filename,position,cid,group,ttid from dcf where filename = '");
_LIT(KSqlUpdate2 , "' and position = ");
_LIT(KSqlInsert , "select filename,position,cid,group,ttid from dcf");
_LIT(KSqlDeleteAll , "delete from dcf");
_LIT(KGroupIdReplacement, "cid:group@localhost");
// MACROS
// LOCAL CONSTANTS AND MACROS

#ifdef RD_MULTIPLE_DRIVE
_LIT( KDbFileLoc, "%c:\\system\\data\\DcfRepDb" );
#endif

// MODULE DATA STRUCTURES
// LOCAL FUNCTION PROTOTYPES
LOCAL_C TInt CreateDataBase(RFs& aFs);

#ifndef RD_MULTIPLE_DRIVE
LOCAL_C TParse DataFile();
#else // RD_MULTIPLE_DRIVE
LOCAL_C TParse DataFile( RFs& aFs );
#endif

LOCAL_C void CreateTablesL(RDbDatabase& aDatabase);
LOCAL_C TInt CreateDataBasePath(RFs& aFs);
// FORWARD DECLARATIONS

//#define _DRM_TESTING
//#define _MEM_HEAP_USAGE

// ============================ LOCAL FUNCTIONS ===============================
#ifdef _DRM_TESTING
LOCAL_C void WriteLogL( const TDesC8& text , RFs &aFs );
LOCAL_C void WriteFileL( const TDesC8& text , RFs &aFs , const TDesC& aName );
LOCAL_C void CreateLogL();
LOCAL_C void WriteL( const TDesC8& aText );
LOCAL_C void WriteL( const TDesC8& aText , TInt aErr );
LOCAL_C void WriteCurrentTimeL();

#ifdef _MEM_HEAP_USAGE
LOCAL_C void WriteHeapAllocL();
#endif //_MEM_HEAP_USAGE

#endif //_DRM_TESTING

// -----------------------------------------------------------------------------
// Testing stuff
// -----------------------------------------------------------------------------
//
#ifdef _DRM_TESTING
LOCAL_C void WriteLogL( const TDesC8& text , RFs &aFs )
    {
    _LIT( KLogFile , "c:\\CDcfRepSrv.txt" );
    WriteFileL( text , aFs , KLogFile );
    }

LOCAL_C void WriteFileL( const TDesC8& text , RFs &aFs , const TDesC& aName )
    {
    RFile file;
    TInt size;
    User::LeaveIfError( file.Open( aFs, aName , EFileWrite ) );
    CleanupClosePushL( file );
    User::LeaveIfError( file.Size( size ) );
    User::LeaveIfError( file.Write( size, text ) );
    CleanupStack::PopAndDestroy(&file); //file
    }

LOCAL_C void CreateLogL()
    {
    RFs fs;
    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);
    RFile file;
    User::LeaveIfError( file.Replace( fs , _L("c:\\CDcfRepSrv.txt") , EFileWrite ) );
    file.Close();
    CleanupStack::PopAndDestroy(&fs); //fs
    }

LOCAL_C void WriteL( const TDesC8& aText )
    {
    RFs fs;
    User::LeaveIfError( fs.Connect() );
    CleanupClosePushL(fs);
    HBufC8* text = HBufC8::NewLC(1000);
    TPtr8 textptr(text->Des() );
    textptr.Append( aText );
    textptr.Append( _L8("\r\n") );
    WriteLogL(textptr , fs);
    CleanupStack::PopAndDestroy(text);
    CleanupStack::PopAndDestroy(&fs); //fs
    WriteCurrentTimeL();
#ifdef _MEM_HEAP_USAGE
    WriteHeapAllocL();
#endif //_MEM_HEAP_USAGE
    }

LOCAL_C void WriteL( const TDesC8& aText , TInt aErr )
    {
    _LIT8(KErr,": %d");
    HBufC8* text = HBufC8::NewLC(1000+20);
    TBuf8<20> num;
    TPtr8 textptr(text->Des());
    textptr.Append(aText);
    num.Format(KErr(),aErr);
    textptr.Append(num);
    WriteL(textptr);
    CleanupStack::PopAndDestroy(text);
    }

LOCAL_C void WriteCurrentTimeL()
    {
    RFs fs;
    User::LeaveIfError( fs.Connect() );
    CleanupClosePushL(fs);
    HBufC8* text = HBufC8::NewLC(100);
    TPtr8 textptr(text->Des() );
    // Date and Time display
    TTime time;
    time.HomeTime();
    TBuf<256> dateString;
    _LIT(KDate,"%*E%*D%X%*N%*Y %1 %2 '%3");
    time.FormatL(dateString,KDate);
    textptr.Append(_L( "\r\n\t\tData:\t" ) );
    textptr.Append( dateString );
    _LIT(KTime,"%-B%:0%J%:1%T%:2%S%:3%+B");
    time.FormatL(dateString,KTime);
    textptr.Append(_L( "\r\n\t\tTime:\t" ) );
    textptr.Append( dateString );
    textptr.Append(_L( "\r\n" ) );
    textptr.Append(_L( "\r\n" ) );
    WriteLogL(textptr , fs);
    CleanupStack::PopAndDestroy(text);
    CleanupStack::PopAndDestroy(&fs); //fs
    }

#ifdef _MEM_HEAP_USAGE
LOCAL_C void WriteHeapAllocL()
    {
    _LIT8(KHeapUsage,"\r\n***** Heap cells allocated: %d *****\r\n");
    TBuf8<256> string;
    TInt size = 0;
    RFs fs;
    User::LeaveIfError( fs.Connect() );
    CleanupClosePushL(fs);
    User::Heap().AllocSize(size);
    string.Format(KHeapUsage(),size);
    WriteLogL(string , fs);
    CleanupStack::PopAndDestroy(&fs); //fs
    }
#endif //_MEM_HEAP_USAGE


#endif //_DRM_TESTING

// -----------------------------------------------------------------------------
// DataFile
// Return TParse which contain database file name
// -----------------------------------------------------------------------------
//
#ifdef RD_MULTIPLE_DRIVE
LOCAL_C TParse DataFile( RFs& aFs )
#else
LOCAL_C TParse DataFile()
#endif
    {
#ifdef _DRM_TESTING
    TRAP_IGNORE( WriteL(_L8("DataFile")) );
#endif

    TParse p;

#ifndef RD_MULTIPLE_DRIVE

    p.Set(KDbFileLocation,NULL,NULL);

#else //RD_MULTIPLE_DRIVE

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

    aFs.DriveToChar( driveNumber, driveLetter );

    TFileName dbFile;
    dbFile.Format( KDbFileLoc, (TUint)driveLetter );

    p.Set(dbFile,NULL,NULL);

#endif

    return p;
    }


// -----------------------------------------------------------------------------
// CreateTablesL
// Create table through database session
// -----------------------------------------------------------------------------
//
LOCAL_C void CreateTablesL(RDbDatabase& aDatabase)
    {
#ifdef _DRM_TESTING
    WriteL(_L8("CreateTablesL"));
#endif

    CDbColSet* columns = CDbColSet::NewLC();

    //filename columns
    TDbCol filename(KColFilename,EDbColLongText16);
    filename.iAttributes = TDbCol::ENotNull;
    columns->AddL(filename);

    //position columns
    TDbCol position(KColPosition,EDbColUint16);
    position.iAttributes = TDbCol::ENotNull;
    columns->AddL(position);

    //content id columns
    TDbCol cid(KColCid,EDbColLongText16);
    cid.iAttributes = TDbCol::ENotNull;
    columns->AddL(cid);

    //content group id columns
    TDbCol group(KColGroupId,EDbColLongText16);
    columns->AddL(group);

    //transaction id columns
    TDbCol ttid(KColTtid,EDbColText16,KTtidLen);
    columns->AddL(ttid);

    aDatabase.CreateTable( KTable,*columns);
    CleanupStack::PopAndDestroy(columns); //columns

    }

// -----------------------------------------------------------------------------
// CreateDataBasePath
// Create database with client side database access
// -----------------------------------------------------------------------------
//
LOCAL_C TInt CreateDataBasePath(RFs& aFs)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("CreateDataBasePath")));
#endif

    TInt err = 0;

#ifndef RD_MULTIPLE_DRIVE

    err = aFs.MkDirAll( DataFile(). DriveAndPath() );

#else //RD_MULTIPLE_DRIVE

    err = aFs.MkDirAll( DataFile( aFs ). DriveAndPath() );

#endif

    return err;
    }

// -----------------------------------------------------------------------------
// CreateDataBase
// Create database with client side database access
// -----------------------------------------------------------------------------
//
LOCAL_C TInt CreateDataBase(RFs& aFs)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("CreateDataBase")));
#endif

    RDbNamedDatabase database;
    TInt err = 0;
    TFileName file;

#ifndef RD_MULTIPLE_DRIVE

    file = DataFile().FullName();


#else // RD_MULTIPLE_DRIVE

    file = DataFile( aFs ).FullName();

#endif

    if (!err)
        {
#ifdef _DRM_TESTING
        TRAP(r,WriteL(_L8("CreateDataBase->DataFile"),err));
#endif
        err = CreateDataBasePath(aFs);

        err = database.Create(aFs,file);
        if (!err)
            {
#ifdef _DRM_TESTING
            TRAP(r,WriteL(_L8("CreateDataBase->database.Create"),err));
#endif
            TRAP( err , CreateTablesL(database) );
#ifdef _DRM_TESTING
            TRAP(r,WriteL(_L8("CreateDataBase->CreateTablesL"),err));
#endif
            }
        database.Close();
        }
    return err;
    }

// -----------------------------------------------------------------------------
// From8To16
// transfer buf from 8 bit to 16 bit
// -----------------------------------------------------------------------------
//
LOCAL_C TInt From8To16( const TDesC8& a8 , HBufC16*& a16 )
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("From8To16")));
#endif

    TInt err = KErrNone;
    a16 = HBufC::NewMax( a8.Length() );
    if ( a16 )
        {
        TPtr ptr( a16->Des() );
        ptr.SetLength( a8.Length() );
        for (TInt i = 0 ; i<a8.Length() ; i++ )
            {
            ptr[i] = ( unsigned char ) a8[i];
            }
        }
    else err = KErrNoMemory;
    return err;
    }

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

// -----------------------------------------------------------------------------
// CDcfRepSrv::CDcfRepSrv
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CDcfRepSrv::CDcfRepSrv():CServer2( EPriorityStandard ),
    iScan(NULL),
    iCidList(NULL),
    iPairList(NULL),
    iState(EStateIdle),
    iArmed( EFalse )
    {

    }

// -----------------------------------------------------------------------------
// CDcfRepSrv::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::ConstructL()
    {
#ifdef _DRM_TESTING
    CreateLogL();
    WriteL(_L8("ConstructL"));
#endif
    StartL(KDcfRepSrvName);
    User::LeaveIfError(iFs.Connect());
    iScan = CFileScan::NewL(iFs);
    OpenDatabaseL();

    User::RenameThread(KDcfRepSrvName);

    iProcWatcher = CProcWatcher::NewL( *this, _L( "*RightsServer*" ), _L( "RightsServer" ) );
    iProcWatcher->StartWatching();
    iArmed = ETrue;
    }


// -----------------------------------------------------------------------------
// CDcfRepSrv::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CDcfRepSrv* CDcfRepSrv::NewLC()
    {
    CDcfRepSrv* self = new( ELeave ) CDcfRepSrv;
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


// Destructor
CDcfRepSrv::~CDcfRepSrv()
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("~CDcfRepSrv")));
#endif

    delete iScan;
    CleanScanInternal();
    CleanDatabase();
    iFs.Close();
    for (TInt i = 0 ; i < iMessageList.Count() ; i++ )
        {
        if ( iMessageList[i]!=NULL && !(iMessageList[i]->IsNull()) )
            {
            iMessageList[i]->Complete(KErrCancel);
            }

        }
    iMessageList.ResetAndDestroy();
    iMessageList.Close();
    }

// -----------------------------------------------------------------------------
// CDcfRepSrv::NewSessionL
// Called when a client requires a new instance.
// -----------------------------------------------------------------------------
CSession2* CDcfRepSrv::NewSessionL(const TVersion &aVersion,
    const RMessage2& /*aMessage*/ ) const
    {
#ifdef _DRM_TESTING
    WriteL(_L8("NewSessionL"));
#endif
    // check we're the right version
    if (!User::QueryVersionSupported(TVersion(KDcfRepMajorVersionNumber,
                KDcfRepMinorVersionNumber,
                KDcfRepBuildVersionNumber),
            aVersion))
        {
        User::Leave(KErrNotSupported);
        }

    // make new session
    return CDcfRepSrvSes::NewL();
    }


// -----------------------------------------------------------------------------
// Startup().
// This function starts the actual DCF Repository server after initializing
// the cleanup stack and active scheduler.
// Returns: TInt: Symbian OS error code.
// -----------------------------------------------------------------------------
//

TInt CDcfRepSrv::Startup( void )
    {
    TInt err = 0;
    TBool clientIsWaiting = EFalse;
    RSemaphore semaphore;

    CTrapCleanup* cleanupStack = CTrapCleanup::New();

    if (cleanupStack == NULL)
        {
        PanicServer(ECreateTrapCleanup);
        }

    // check if the client wants to be signaled that we are ready
    if ( semaphore.OpenGlobal(KDcfRepSemaphoreName) == KErrNone )
        {
        clientIsWaiting = ETrue;
        }

    TRAP(err, StartupL());

    // release client side waiting
    if (clientIsWaiting)
        {
        semaphore.Signal();
        semaphore.Close();
        }

    if (err != KErrNone)
        {
        PanicServer(ESrvCreateServer);
        }

    delete cleanupStack;
    cleanupStack = NULL;
    return KErrNone;
    }


// -----------------------------------------------------------------------------
// StartupL().
// This function starts the actual DCF Repository after initializing scheduler
// -----------------------------------------------------------------------------
//

void CDcfRepSrv::StartupL()
    {
    // Construct active scheduler
    CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
    CleanupStack::PushL(activeScheduler) ;

    // Install active scheduler
    // We don't need to check whether an active scheduler is already installed
    // as this is a new thread, so there won't be one
    CActiveScheduler::Install(activeScheduler);

    // Construct our server
    CDcfRepSrv::NewLC();

    // Start handling requests
    CActiveScheduler::Start();

    CleanupStack::PopAndDestroy(2);    //  activeScheduler and anonymous CDcfRepSrv
    }

void CDcfRepSrv::PanicServer(TDcfRepSrvPanic aPanic)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("PanicServer")));
    r =  0;
#endif

    User::Panic(KDcfRepSrv, aPanic);
    }


// -----------------------------------------------------------------------------
// AddFileL()
// The function will add a file info into database
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::AddFileL( const TDesC& aFile )
    {
#ifdef _DRM_TESTING
    WriteL(_L8("AddFileL"));
#endif

    TInt err = 0;
    TInt state = iState;
    TBool flag = EFalse;

    // to process the file as doing scanning fully for file system
    iState = EStateFullScan;
    err = ProcessFile(aFile , flag);
    // change the state back
    iState = state;
    User::LeaveIfError(err);
    if ( flag == ENoDcf )
        {
        User::Leave(KErrNotSupported);
        }
    else if (flag == EOma2Dcf)
        {
        AddDomainRoL(aFile);
        }
    }

// -----------------------------------------------------------------------------
// AddDomainRoL()
// The function will add a file info into database
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::AddDomainRoL( const TDesC& aFile )
    {
#ifdef _DRM_TESTING
    WriteL(_L8("AddDomainRoL"));
#endif

    __UHEAP_MARK;
    RFile file;
    TPtr8 ptr(NULL,0,0);
    CContent* content =NULL;
    User::LeaveIfError(file.Open(iFs, aFile, EFileShareReadersOrWriters | EFileWrite ) );
    CleanupClosePushL(file);
    content = CContent::NewL(file);
    CleanupStack::PushL(content);
    User::LeaveIfError(content->AgentSpecificCommand(EEmbedDomainRo,
            KNullDesC8, ptr ));
    CleanupStack::PopAndDestroy(2); // content, file
    __UHEAP_MARKEND;
    }


// -----------------------------------------------------------------------------
// OpenDatabaseL()
// The function will open database
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::OpenDatabaseL()
    {
#ifdef _DRM_TESTING
    WriteL(_L8("OpenDatabaseL"));
#endif


    TInt err = CreateDataBase(iFs);
    if ( err==KErrAlreadyExists )
        {
        err = KErrNone;
        }

    User::LeaveIfError(iDbs.Connect());

#ifndef RD_MULTIPLE_DRIVE

    User::LeaveIfError(iDb.Open(iDbs,DataFile().FullName()));

#else // RD_MULTIPLE_DRIVE

    User::LeaveIfError(iDb.Open(iDbs,DataFile(iFs).FullName()));

#endif
    }


// -----------------------------------------------------------------------------
// CleanTableL()
// The function will empty the talbe
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::CleanTableL()
    {
#ifdef _DRM_TESTING
    WriteL(_L8("CleanTableL"));
#endif

    User::LeaveIfError(iDb.Execute(KSqlDeleteAll()));
    }

// -----------------------------------------------------------------------------
// ProcessFile()
// This function check if the file is DRM protected and add it into database.
// -----------------------------------------------------------------------------
//
TInt CDcfRepSrv::ProcessFile(const TDesC& aFile , TInt& aType)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("ProcessFile")));
#endif

    TInt err = 0;
    aType = ENoDcf;

    TRAP(err , CheckFileL(aFile , aType));
    if (aType)
        {
        TRAP(err , StoreFileL(aFile,aType));
        }
    return err;
    }

// -----------------------------------------------------------------------------
// CheckFileL()
// check if it is target file
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::CheckFileL(const TDesC& aFile , TInt& aType)
    {
#ifdef _DRM_TESTING
    WriteL(_L8("CheckFileL"));
#endif

    RFile f;
    TInt pos = 0;
    TBuf8<256> buf;

    switch(iState)
        {
        case EStateFullScan:
        case EStateScan:
                {
                User::LeaveIfError(f.Open(iFs,aFile,EFileRead|EFileShareReadersOrWriters));
                CleanupClosePushL(f);
                User::LeaveIfError(f.Seek(ESeekStart,pos));
                User::LeaveIfError(f.Read(0,buf));
                CleanupStack::PopAndDestroy(&f);
                if (COma1Dcf::IsValidDcf(buf))
                    {
                    aType = EOma1Dcf;
                    }
#ifdef __DRM_OMA2
                else if (COma2Dcf::IsValidDcf(buf))
                    {
                    aType = EOma2Dcf;
                    }
#endif
                else
                    {
                    aType = ENoDcf;
                    }
                }
            break;
        case EStateSetTtid:
                {
                TParse p;
                User::LeaveIfError(p.Set(aFile,NULL,NULL));
                if ( !p.Ext().Compare( KOma2DcfExtension ) ||
                    !p.Ext().Compare( KOma2DcfExtensionAudio ) ||
                    !p.Ext().Compare( KOma2DcfExtensionVideo ) )
                    {
                    User::LeaveIfError(f.Open(iFs,aFile,EFileRead|EFileShareReadersOrWriters));
                    CleanupClosePushL(f);
                    User::LeaveIfError(f.Seek(ESeekStart,pos));
                    User::LeaveIfError(f.Read(0,buf));
                    CleanupStack::PopAndDestroy(&f);
                    if (COma1Dcf::IsValidDcf(buf))
                        {
                        aType = EOma1Dcf;
                        }
#ifdef __DRM_OMA2
                    else if (COma2Dcf::IsValidDcf(buf))
                        {
                        aType = EOma2Dcf;
                        }
#endif
                    else
                        {
                        aType = ENoDcf;
                        }
                    }
                }
            break;
        default:
            ;
        }
    }

// -----------------------------------------------------------------------------
// StoreFile()
// save file info into database
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::StoreFileL(const TDesC& aFile , TInt aType)
    {
#ifdef _DRM_TESTING
    WriteL(_L8("StoreFileL"));
#endif

    RFile f;
    User::LeaveIfError(f.Open(iFs,aFile,EFileRead|EFileShareReadersOrWriters));
    CleanupClosePushL(f);
    TInt i = 0;
    TInt setTtid = -1;
    HBufC16* cid = NULL;
    HBufC16* ttid = NULL;
    HBufC16* group = NULL;

    if (aType == EOma1Dcf)
        {
        COma1Dcf* d = COma1Dcf::NewL(f);
        CleanupStack::PushL(d);
        User::LeaveIfError( From8To16( *(d->iContentID) , cid ) );
        CleanupStack::PopAndDestroy(d);
        CleanupStack::PushL(cid);
        ttid = HBufC::NewMaxLC(16);
        *ttid = KNullDesC16;
        UpdateDatabaseL(aFile , KStartPosition , *cid , KNullDesC() , *ttid);
        if (iCidList)
            {
            for (i = 0; i<iCidList->Count(); i++)
                {
                HBufC* temp = NULL;
                User::LeaveIfError( From8To16(*((*iCidList)[i]) , temp ) );
                CleanupStack::PushL(temp);
                if (!temp->Compare(*cid))
                    {
                    delete (*iCidList)[i];
                    iCidList->Remove(i);
                    CleanupStack::PopAndDestroy(temp);
                    break;
                    }
                CleanupStack::PopAndDestroy(temp); //temp
                }
            if (iCidList->Count()<=0)
                {
                CompleteScanning(KErrNone);
                }
            }
        CleanupStack::PopAndDestroy(2); //cid,ttid
        }
    else if (aType == EOma2Dcf)
        {
        COma2Dcf* d = COma2Dcf::NewL(f);
        CleanupStack::PushL(d);

        // Set group ID and content ID for this entry
        if (d->iGroupId)
            {
            User::LeaveIfError( From8To16( *(d->iGroupId) , group ) );

            // replace the content ID for this entry with a placeholder to prevent
            // that the file is listed wrongly under the group ID
            cid = KGroupIdReplacement().AllocL();
            }
        else
            {
            User::LeaveIfError( From8To16( *(d->iContentID) , cid ) );
            group = HBufC::NewMaxL(16);
            *group = KNullDesC16;
            }
        CleanupStack::PushL(cid);
        CleanupStack::PushL(group);

        if (iState == EStateSetTtid)
            {
            for (i = 0; iPairList && i<iPairList->Count() && !ttid; i++)
                {
                HBufC* temp = NULL;
                User::LeaveIfError( From8To16(*((*iPairList)[i]->iCid) , temp ) );
                CleanupStack::PushL(temp);
                if (!temp->Compare(*cid))
                    {
                    User::LeaveIfError( From8To16(*((*iPairList)[i]->iTtid) , ttid ) );

                    // EFileWrite is needed for this case
                    // So we cannot do it here. we must close the file
                    setTtid = i;
                    }
                CleanupStack::PopAndDestroy(temp); //temp
                }
            }
        if (!ttid)
            {
            if (d->iTransactionTracking)
                {
                User::LeaveIfError( From8To16( *(d->iTransactionTracking) , ttid ) );
                }
            else
                {
                ttid = HBufC::NewMaxL(16);
                *ttid = KNullDesC16;
                }
            }
        CleanupStack::PushL(ttid);

        UpdateDatabaseL(aFile , KStartPosition , *cid , *group , *ttid);
        if (iCidList)
            {
            for (i = 0; i<iCidList->Count(); i++)
                {
                HBufC* temp = NULL;
                User::LeaveIfError( From8To16(*((*iCidList)[i]) , temp ) );
                CleanupStack::PushL(temp);
                if (!temp->Compare(*cid))
                    {
                    delete (*iCidList)[i];
                    iCidList->Remove(i);
                    CleanupStack::PopAndDestroy(temp);
                    break;
                    }
                CleanupStack::PopAndDestroy(temp); //temp
                }
            if (iCidList->Count()<=0)
                {
                CompleteScanning(KErrNone);
                }
            }
        CleanupStack::PopAndDestroy(4); // group,ttid,cid,d
        }

    CleanupStack::PopAndDestroy(&f); // f

    if (setTtid>=0)
        {
        ResetTtidL( aFile , *((*iPairList)[setTtid]->iTtid));
        }
    }

// -----------------------------------------------------------------------------
// ResetTtidL()
// save new ttid into file
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::ResetTtidL(
    const TDesC& aFile,
    const TDesC8& aTtid
    )
    {
#ifdef _DRM_TESTING
    WriteL(_L8("ResetTtidL"));
#endif

    RFile f;
    User::LeaveIfError(f.Open(iFs,aFile, EFileWrite|EFileShareReadersOrWriters ));
    CleanupClosePushL(f);
    COma2Dcf* d = COma2Dcf::NewL(f);
    CleanupStack::PushL(d);
    ResetTtidL(d,aTtid);
    CleanupStack::PopAndDestroy(2); // f,d
    }

// -----------------------------------------------------------------------------
// ResetTtidL()
// save new ttid into file
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::ResetTtidL(
    COma2Dcf* aDcf,
    const TDesC8& aTtid
    )
    {
#ifdef _DRM_TESTING
    WriteL(_L8("ResetTtidL"));
#endif

    aDcf->SetTransactionIdL(aTtid);
    }

// -----------------------------------------------------------------------------
// UpdateDatabaseL()
// save info into database
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::UpdateDatabaseL(
    const TDesC& aFile,
    TInt aPos,
    const TDesC& aCid ,
    const TDesC& aGroupId ,
    const TDesC& aTtid)
    {
#ifdef _DRM_TESTING
    WriteL(_L8("UpdateDatabaseL"));
#endif

    HBufC* sql = NULL;
    TPtr ptr(NULL,0,0);
    TBuf<4> num;
    sql = HBufC::NewMaxLC(aFile.Length()+200);
    ptr.Set(sql->Des());
    ptr.SetLength(0);
    ptr.Append(KSqlUpdate1);
    ptr.Append(aFile);
    ptr.Append(KSqlUpdate2);
    num.Num(aPos);
    ptr.Append(num);

    iView.Close();

    User::LeaveIfError(
        iView.Prepare(
            iDb,TDbQuery(ptr),
            TDbWindow::EUnlimited,
            RDbView::EUpdatable
            )
        );
    User::LeaveIfError(iView.EvaluateAll());
    if (iView.FirstL())
        {
        iView.UpdateL();
        iView.SetColL(KOrdCid,aCid);
        iView.SetColL(KOrdGroupId,aGroupId);
        iView.SetColL(KOrdTtid,aTtid);
        iView.PutL();
        }
    else
        {
        iView.Reset();
        iView.Close();
        iView.Prepare(
            iDb,TDbQuery(KSqlInsert),
            TDbWindow::EUnlimited,
            RDbView::EInsertOnly
            );
        iView.InsertL();
        iView.SetColL(KOrdFilename,aFile);
        iView.SetColL(KOrdPosition,aPos);
        iView.SetColL(KOrdCid,aCid);
        iView.SetColL(KOrdGroupId,aGroupId);
        iView.SetColL(KOrdTtid,aTtid);
        iView.PutL();
        }
    iView.Reset();
    iView.Close();
    CleanupStack::PopAndDestroy(sql); //sql
    }

// -----------------------------------------------------------------------------
// State()
// This function returns the state of the Server
// -----------------------------------------------------------------------------
//
TInt CDcfRepSrv::State() const
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("State")));
#endif

    return iState;
    }

// -----------------------------------------------------------------------------
// SetState()
// This function set the state of the Server
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::SetState(TServerState aMode)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("SetState")));
#endif

    iState = aMode;
    }


// -----------------------------------------------------------------------------
// CompleteScanning().
// This function complete request from client
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::CompleteScanning(TInt aRet)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("CompleteScanning")));
#endif

    if ( iScan->IsActive() )
        {
        iScan->Cancel();
        }

    for (TInt i = 0 ; i<iMessageList.Count() ; i++ )
        {
        if ( iMessageList[i] && !(iMessageList[i]->IsNull()) )
            {
            iMessageList[i]->Complete(aRet);
            }
        }
    iMessageList.ResetAndDestroy();

    CleanScanInternal();
    iState = EStateIdle;
    }

// -----------------------------------------------------------------------------
// SetMessage().
// This function save the incomplete message to server
// -----------------------------------------------------------------------------
//
RMessage2* CDcfRepSrv::SetMessageL(const RMessage2& aMessage)
    {
#ifdef _DRM_TESTING
    WriteL(_L8("SetMessageL"));
#endif
    RMessage2* m = NULL;
    m = new (ELeave) RMessage2(aMessage);
    iMessageList.AppendL(m);
    return m;
    }


// -----------------------------------------------------------------------------
// RemoveMessage().
// This function to remove the imcomplete message from server if it is still there
// when session is deleted
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::RemoveMessageL( const RMessage2* aMessage )
    {
    for (TInt i = 0 ; i<iMessageList.Count() ; i++ )
        {
        if ( iMessageList[i] == aMessage )
            {
            delete iMessageList[i];
            iMessageList[i] = NULL;
            iMessageList.Remove( i );
            return;
            }
        }
    return;
    };


// -----------------------------------------------------------------------------
// SetCidList().
// This function set content ID List
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::SetCidList(RPointerArray<HBufC8>*& aList)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("SetCidList")));
#endif

    if (iCidList)
        {
        iCidList->ResetAndDestroy();
        iCidList->Close();
        delete iCidList;
        }
    iCidList = aList;
    }

// -----------------------------------------------------------------------------
// SetPairList().
// This function set list of pairs for content ID and transation ID
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::SetPairList(RPointerArray<CPair>*& aList)
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("SetPairList")));
#endif

    if (iPairList)
        {
        iPairList->ResetAndDestroy();
        iPairList->Close();
        delete iPairList;
        }
    iPairList = aList;
    }


// -----------------------------------------------------------------------------
// Scan()
// This function scan the file system
// -----------------------------------------------------------------------------
//
TInt CDcfRepSrv::Scan()
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("Scan")));
#endif

    TInt err = 0;
    if (iState == EStateFullScan)
        {
        TRAP(err,CleanTableL());
        }
    err = iScan->SearchContent(this);
    if (err)
        {
        CleanScanInternal();
        iState = EStateIdle;
        }
    return err;
    }

void CDcfRepSrv::CleanScanInternal()
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("CleanScanInternal")));
#endif

    if (iCidList)
        {
        iCidList->ResetAndDestroy();
        iCidList->Close();
        delete iCidList;
        iCidList = NULL;
        }
    if (iPairList)
        {
        iPairList->ResetAndDestroy();
        iPairList->Close();
        delete iPairList;
        iPairList = NULL;
        }
    }

void CDcfRepSrv::CleanDatabase()
    {
#ifdef _DRM_TESTING
    TRAPD(r,WriteL(_L8("CleanDatabase")));
#endif

    iView.Close();
    iDb.Close();
    iDbs.Close();
    }

// -----------------------------------------------------------------------------
// CDcfRepSrv::WatchedObjectChangedL
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::WatchedObjectChangedL( const TDesC& aObject )
    {
    DRMLOG( _L( "CDcfRepSrv::WatchedObjectChangedL ->" ) );
    DRMLOG( aObject );

    if ( aObject.Left( KProcIdentifier().Length() ) == KProcIdentifier && iArmed )
        {
#ifdef _DEBUG
        DRMLOG( _L( "Peer process killed (DEBUG mode, not rebooting)" ) );
#else
        DRMLOG( _L( "Peer process killed, rebooting" ) );
        RStarterSession starter;
        User::LeaveIfError( starter.Connect() );
        starter.Shutdown();
        starter.Close();
#endif
        }

    DRMLOG( _L( "CDRMRightsServer::WatchedObjectChangedL <-" ) );
    }

// -----------------------------------------------------------------------------
// CDcfRepSrv::StopWatchingL
// -----------------------------------------------------------------------------
//
void CDcfRepSrv::StopWatchingL()
    {
    DRMLOG( _L( "CDcfRepSrv::StopWatchingL ->" ) );
    iArmed = EFalse;
    DRMLOG( _L( "CDRMRightsServer::StopWatchingL <-" ) );
    }

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

// -----------------------------------------------------------------------------
// E32 Entry for Executable
// -----------------------------------------------------------------------------

TInt E32Main()
    {
    return CDcfRepSrv::Startup();
    }

//  End of File