omadrm/drmengine/dcfrepository/server/src/DcfRepSrv.cpp
changeset 0 95b198f216e5
child 18 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/dcfrepository/server/src/DcfRepSrv.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,1254 @@
+/*
+* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  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
+
+    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