skins/AknSkins/srvsrc/aknssrvactivebackupdataclient.cpp
changeset 0 05e9090e2422
child 32 d9c996538b26
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skins/AknSkins/srvsrc/aknssrvactivebackupdataclient.cpp	Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,1192 @@
+/*
+* Copyright (c) 2007-2008 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:  Skin server's active data owner in backup/restore.
+*
+*/
+
+
+#include <f32file.h>
+
+#include "aknssrvactivebackupdataclient.h"
+#include "AknsSrvUtils.h"
+
+#include "AknsDebug.h"
+
+// Maximum size of header info.
+const TUint KMaxHeaderSize = 256;
+
+// number of bytes to read from file per block
+const TUint KCheckSumBlockSize = 128;
+
+// Default size of restore/backup stream size in bytes.
+const TUint KArbitraryNumber=1024;
+
+// 8 bytes
+const TUint K8Bytes = 8;
+// 16 bytes
+const TUint K16Bytes = 16;
+// Length of extension (including preceding dot).
+const TInt KExtensionLength = 4;
+
+_LIT( KSkinRootDir,":\\resource\\skins\\" );
+
+// ======== MEMBER FUNCTIONS ========
+
+// Skin files are backed up in the following format.
+// filename contains drive and path in addition to filename.
+// <checksum><filesize><filenamelen><filename>
+
+// ---------------------------------------------------------------------------
+// Symbian constructor.
+// ---------------------------------------------------------------------------
+//
+CAknsSrvActiveBackupDataClient* CAknsSrvActiveBackupDataClient::NewL( RFs& aFsSession )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::NewL" );
+    CAknsSrvActiveBackupDataClient* self =
+        new( ELeave ) CAknsSrvActiveBackupDataClient( aFsSession );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CAknsSrvActiveBackupDataClient::~CAknsSrvActiveBackupDataClient()
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::destructor" );
+    iFileArray.Reset();
+    iFileArray.Close();
+    iFile.Close();
+    delete iBuffer;
+    }
+
+// ---------------------------------------------------------------------------
+// Prepare for backup and restore ( no actions).
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::PrepareForBURL( TInt /*aBackupStateValue*/ )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::PrepareForBURL" );
+    }
+
+// ---------------------------------------------------------------------------
+// Inform that all data has been backed up or restored.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::AllSnapshotsSuppliedL()
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::AllSnapshotsSuppliedL" );
+    // Finalize and cleanup.
+    return;
+    }
+
+// ---------------------------------------------------------------------------
+// Not supported.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::ReceiveSnapshotDataL(
+    TDriveNumber /*aDrive*/, TDesC8& /*aBuffer*/, TBool /*aLastSection*/)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::ReceiveSnapshotDataL" );
+    User::Leave( KErrNotSupported );
+    }
+
+// ---------------------------------------------------------------------------
+// Make a guess about data size.
+// ---------------------------------------------------------------------------
+//
+TUint CAknsSrvActiveBackupDataClient::GetExpectedDataSize(
+    TDriveNumber /*aDrive*/)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetExpectedDataSize" );
+    // we have no idea at this point - we even don't know what is to be
+    // backed up yet
+    return KArbitraryNumber;
+    }
+
+// ---------------------------------------------------------------------------
+// Not supported.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::GetSnapshotDataL(
+    TDriveNumber /*aDrive*/, TPtr8& /*aBuffer*/, TBool& /*aFinished*/)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetSnapshotDataL" );
+    User::Leave( KErrNotSupported );
+    }
+
+// ---------------------------------------------------------------------------
+// Initialize for backup - collect to-be-backed-up-files.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::InitialiseGetBackupDataL(
+    TDriveNumber aDrive)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseGetBackupDataL" );
+    DoInitialiseGetBackupDataL( aDrive );
+    }
+
+// ---------------------------------------------------------------------------
+// Run state machine for backup. Each file is opened and streamed to the
+// BUR engine.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::GetBackupDataSectionL(
+    TPtr8& aBuffer, TBool& aFinished)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL" );
+    // Make sure that the buffer is empty and starts from the beginning
+    aBuffer.SetLength(0);
+
+    // don't assume they set it to false
+    aFinished = EFalse;
+    // any files to backup
+    if( iFileArray.Count() == 0 )
+        {
+        // nothing to backup - just return the finished flag
+        aFinished = ETrue;
+        // clear the list and stop.
+        iFileArray.Reset();
+        AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL no files" );
+        return;
+        }
+
+    // run the state machine
+    while( ETrue )
+        {
+        switch( iBackupState )
+            {
+            // open a file for processing
+            case EBackupNoFileOpen:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState );
+                if( iFileIndex >= iFileArray.Count() )
+                    {
+                    // all files have been processed - send the finished flag
+                    aFinished = ETrue;
+                    // clear the list and stop.
+                    iFileArray.Reset();
+                    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL all processed" );
+                    return;
+                    }
+
+                // open file to send
+                TInt rc=iFile.Open( iFsSession,
+                                    iFileArray[iFileIndex].FullName(),
+                                    ( EFileRead | EFileShareExclusive | EFileStream ) );
+                if( rc != KErrNone )
+                    {
+                    // there's nothing we can do if we can't open the file
+                    // so we just skip it
+                    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL skip file" );
+                    ++iFileIndex;
+                    break;
+                    }
+                iBackupState = EBackupOpenNothingSent;
+                break;
+                }
+            // nothing sent (so far) for this file - send the header info
+            case EBackupOpenNothingSent:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState );
+                TInt fileSize;
+                TInt retValue = iFile.Size( fileSize );
+                if( retValue != KErrNone || fileSize == 0 )
+                    {
+                    // empty or unreadable - skip this file
+                    iBackupState = EBackupEndOfFile;
+                    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL skip file2" );
+                    break;
+                    }
+
+                // build the header - this is an instance member because it
+                // has to persist over multiple calls to this method
+                TPtr headerPtr = iBuffer->Des();
+
+                // get the checksum - only grab last 4 bytes - enough to be satisfied that
+                // the backup and restore worked ok
+                TUint64 checksum = CheckSumL( iFile ) & 0xffffffff;
+
+                // build the header - note NOT AppendFormat(); wipes out previous content.
+                // <no of files><checksum><filesize><filenamelen><filename>
+                headerPtr.Format(_L("%8x%8lx%8x%8x"),
+                    iFileArray.Count(),
+                    checksum,
+                    fileSize,
+                    iFileArray[iFileIndex].FullName().Length());
+                headerPtr.Append( iFileArray[iFileIndex].FullName() );
+
+                // we need it to look like an 8bit buffer
+                TPtr8 headerPtr8(
+                    (TUint8*)headerPtr.Ptr(),
+                    headerPtr.Size(),
+                    headerPtr.Size() );
+
+                // Check how much room is left in the buffer.
+                // it starts out empty when we get it from the BUE
+                TInt available = aBuffer.MaxSize() - aBuffer.Size();
+
+                // Check is there enough room for the whole header.
+                TBool enoughRoom = headerPtr8.Size() < available;
+
+                // append the header to the buffer (only till it's full)
+                aBuffer.Append(
+                    headerPtr8.Ptr(),
+                    enoughRoom ? headerPtr8.Size() : available) ;
+
+                // decide what needs to happen next
+                // if complete then we need data, otherwise we need to put
+                // the rest of the header in the next chunk
+                if( enoughRoom )
+                    {
+                    iBackupState = EBackupOpenAllHeaderSent;
+                    }
+                else
+                    {
+                    // we need to keep track of how much of the header has
+                    // been sent so that we only send the reminder on the next
+                    // iteration
+                    iHeaderSent = available;
+                    iBackupState = EBackupOpenPartHeaderSent;
+                    }
+
+                // if the buffer's full we need to return control to the backup engine
+                // Because the finishedFlag is not set, the BUE will process this
+                // chunk and then ask for another
+                if( aBuffer.Size() == aBuffer.MaxSize() )
+                    {
+                    return;
+                    }
+                break;
+                }
+            // need to send the rest of the header
+            case EBackupOpenPartHeaderSent:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState );
+                // get back the header - this is already loaded with the necessary info
+                // from the previous state we were in
+                TPtr headerPtr = iBuffer->Des();
+
+                // we need it to look like an 8bit buffer
+                TPtr8 headerPtr8(
+                    (TUint8*)headerPtr.Ptr(),
+                    headerPtr.Size(),
+                    headerPtr.Size() );
+
+                // Check how many bytes have we yet to send.
+                TInt bytesRemaining = headerPtr.Size() - iHeaderSent;
+
+                // Check how much room in the buffer.
+                TInt available = aBuffer.MaxSize() - aBuffer.Size();
+
+                // enough, if not send as much as we can
+                TBool enoughRoom = bytesRemaining < available;
+                aBuffer.Append(
+                    headerPtr8.Ptr() + iHeaderSent,
+                    enoughRoom ? bytesRemaining : available );
+
+                if( enoughRoom )
+                    {
+                    iHeaderSent = 0; // ready for next header
+                    iBackupState = EBackupOpenAllHeaderSent;
+                    }
+                else
+                    {
+                    iHeaderSent += available; // ready to do round again
+                    // state remains as EBackupOpenPartHeaderSent
+                    }
+
+                // if the buffer's full we need to return control to the backup engine
+                // Because the finishedFlag is not set, the BUE will process this
+                // chunk and then ask for another
+                if( aBuffer.Size() == aBuffer.MaxSize() )
+                    {
+                    return;
+                    }
+                break;
+                }
+            // need to send some data
+            case EBackupOpenAllHeaderSent:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState );
+                // how many bytes can we send
+                TInt available = aBuffer.MaxSize() - aBuffer.Size();
+
+                // create a buffer for this data (plus one for PtrZ)
+                HBufC8* transferBuffer = HBufC8::NewLC( available + 1 );
+                TPtr8 bufferToSend = transferBuffer->Des();
+
+                // get the data
+                User::LeaveIfError( iFile.Read( bufferToSend, available ) );
+
+                // Check how much did we actually read.
+                TInt bytesRead = bufferToSend.Size();
+
+                // EOF
+                if( bytesRead == 0 )
+                    {
+                    CleanupStack::PopAndDestroy( transferBuffer );
+                    iBackupState = EBackupEndOfFile;
+                    break;
+                    }
+
+                // add it to the aBuffer
+                aBuffer.Append( bufferToSend.PtrZ(), bytesRead );
+
+                // tidy up
+                CleanupStack::PopAndDestroy( transferBuffer );
+
+                // if the buffer's full we need to return control to the backup engine
+                if( aBuffer.Size() == aBuffer.MaxSize() )
+                    {
+                    return;
+                    }
+                break;
+                }
+            // At the end of the current file.
+            case EBackupEndOfFile:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::GetBackupDataSectionL state %d", iBackupState );
+
+                // how many bytes can we send
+                if ( aBuffer.Size() != 0 )
+                    {
+                    TInt available = aBuffer.MaxSize() - aBuffer.Size();
+                    // pad the end of the buffer with NULL.
+                    HBufC8* transferBuffer = HBufC8::NewLC( available + 1 );
+                    TPtr8 bufferToSend = transferBuffer->Des();
+                    bufferToSend.FillZ();
+                    aBuffer.Append( bufferToSend.PtrZ(), available );
+                    CleanupStack::PopAndDestroy( transferBuffer );
+                    if( aBuffer.Size() != aBuffer.MaxSize() )
+                        {
+                        // Sanity check
+                        User::Leave( KErrGeneral );
+                        }
+                    }
+                // Close file and move on to next file.
+                iFile.Close();
+                ++iFileIndex;
+                // Start all over again.
+                iBackupState = EBackupNoFileOpen;
+                break;
+                }
+            default:
+                {
+                // not reachable
+                return;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Initialize restore.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::InitialiseRestoreBaseDataL(
+    TDriveNumber /*aDrive*/ )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseRestoreBaseDataL" );
+    // this is the first state of the restore state machine
+    iRestoreState = ERestoreNumberOfFiles;
+    // to keep track in the state machine whether any data was actually sent
+    iDataRestored = EFalse;
+    iFilesRestored = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// Run state machine for restore. Receive stream from BUR engine and turn it
+// to file(s).
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL(
+    TDesC8& aBuffer, TBool aFinished )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL" );
+    // convert the buffer - this is KMaxHeaderSize=256
+    TInt bufferIndex;
+    TPtr bufPtr = iBuffer->Des();
+
+    // used to walk the buffer
+    // got a new buffer - because each time this method is called, we have a
+    // fresh chunk of data
+    bufferIndex = 0;
+
+    // to mark when the state machine is through
+    TBool done = EFalse;
+
+    // check whether this is an empty restore
+    if( aFinished && !iDataRestored )
+        {
+        // we have to do this and not rely on aFinishedFlag alone, because
+        // if aFinished is used, we'll process the last state of the machine
+        // which does tidyup, except that if there was no data, no tidyup should
+        // be done
+        AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL empty restore" );
+        return;
+        }
+
+    // run the machine
+    do
+        {
+        // Check how many bytes are there available in the buffer for processing.
+        TInt bytesAvailable = aBuffer.Length() - bufferIndex;
+        // the reason why we are testing finishedFlag is because we must
+        // make sure we re-enter the machine to do the tidyup
+        if( bytesAvailable <= 0 && !aFinished )
+            {
+            // ran out of data in the chunk
+            // so we return and wait for more data to arrive
+            return;
+            }
+
+        if( aFinished &&
+            iRestoreState != ERestoreComplete &&
+            iRestoreState != ERestoreExpectMoreData )
+            {
+            // ran out of data early
+            // will be ERestoreComplete if data not aligned on 128
+            // will be ERestoreExpectMoreData if data aligned on 128
+            User::Leave( KErrCorrupt );
+            }
+        // yep there was some data in the chunk if we got here
+        if( bytesAvailable > 0 )
+            {
+            iDataRestored = ETrue;
+            }
+        switch( iRestoreState )
+            {
+            case ERestoreNumberOfFiles: // 16 bytes
+                {
+                TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable;
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // stick it in the heap buffer
+                bufPtr.Zero();
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == K8Bytes )
+                    {
+                    // If file size is now read, read file name size next.
+                    iRestoreState = ERestoreExpectChecksum;
+                    }
+
+                break;
+                }
+            case ERestoreExpectChecksum:
+                {
+                // first of all, process the heap buffer to extract the checksum
+                TLex lex( bufPtr );
+                lex.SkipSpace();
+                lex.Val( iNumberofFiles, EHex );
+
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // if we have 16 bytes, get them;
+                // otherwise get what we have available.
+                // if not complete then we need to go around again to get the rest
+                TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable;
+
+                // extract the bytes
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // stick it in the heap buffer
+                bufPtr.Zero();
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == 8 )
+                    {
+                    // If complete checksum is available, move on to filesize.
+                    iRestoreState = ERestoreExpectFileSize;
+                    }
+                else
+                    {
+                    // Otherwise continue reading the checksum.
+                    iRestoreState = ERestoreExpectMoreChecksum;
+                    }
+                break;
+                }
+            // checksum overran buffer on first/subsequent read.
+            case ERestoreExpectMoreChecksum:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // Check how many more bytes do we want.
+                TInt bytesNeeded=( K8Bytes - bufPtr.Length() ) << 1;
+                TInt bytesToGet=
+                    bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable;
+
+                // extract the bytes
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // append it to the heap buffer
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == K8Bytes )
+                    {
+                    // If complete checksum is now available, move on to filesize.
+                    iRestoreState = ERestoreExpectFileSize;
+                    }
+                else
+                    {
+                    // same state : ERestoreExpectMoreChecksum;
+                    }
+                break;
+                }
+            case ERestoreExpectFileSize: // 16 bytes
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // first of all, process the heap buffer to extract the checksum
+                TLex lex( bufPtr );
+                lex.SkipSpace();
+                lex.Val( iChecksum, EHex );
+
+                // now start getting the file size
+                TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable;
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // stick it in the heap buffer
+                bufPtr.Zero();
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == K8Bytes )
+                    {
+                    // If file size is now read, read file name size next.
+                    iRestoreState = ERestoreExpectFileNameSize;
+                    }
+                else
+                    {
+                    // Otherwise continue reading the file size.
+                    iRestoreState = ERestoreExpectMoreFileSize;
+                    }
+                break;
+                }
+            // file size didn't fit into one buffer
+            case ERestoreExpectMoreFileSize:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // Check how many more bytes do we want.
+                TInt bytesNeeded = ( K8Bytes - bufPtr.Length() ) << 1;
+                TInt bytesToGet = bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable;
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // append it to the heap buffer
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == K8Bytes )
+                    {
+                    // If file size is now read, read file name size next.
+                    iRestoreState = ERestoreExpectFileNameSize;
+                    }
+                else
+                    {
+                    // same state ERestoreExpectMoreFileSize;
+                    }
+                break;
+                }
+            // the size of the file name to restore
+            case ERestoreExpectFileNameSize:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // first of all, process the heap buffer to extract the file size
+                TLex lex( bufPtr );
+                lex.SkipSpace();
+                lex.Val( iFileSize, EHex );
+
+                // now start getting the file name size
+                TInt bytesToGet = bytesAvailable >= K16Bytes ? K16Bytes : bytesAvailable;
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // stick it in the heap buffer
+                bufPtr.Zero();
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == K8Bytes )
+                    {
+                    // If filename size is now read, read filename next.
+                    iRestoreState = ERestoreExpectFileName;
+                    }
+                else
+                    {
+                    // Otherwise, continue reading the filename size.
+                    iRestoreState = ERestoreExpectMoreFileNameSize;
+                    }
+                break;
+                }
+            // the file name size overran the buffer
+            case ERestoreExpectMoreFileNameSize:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // Check how many more bytes do we want.
+                TInt bytesNeeded = ( K8Bytes - bufPtr.Length() ) << 1;
+                TInt bytesToGet = bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable;
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // append it to the heap buffer
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == K8Bytes )
+                    {
+                    // If filename size is now read, read filename next.
+                    iRestoreState = ERestoreExpectFileName;
+                    }
+                else
+                    {
+                    // same state ERestoreExpectMoreFileNameSize;
+                    }
+                break;
+                }
+            case ERestoreExpectFileName:  // the name of the file to restore
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // first of all, process the heap buffer to extract the file name size
+                TLex lex( bufPtr );
+                lex.SkipSpace();
+                lex.Val( iFileNameSize, EHex );
+
+                // now start getting the file name
+                TInt bytesToGet = bytesAvailable >= iFileNameSize << 1 ? iFileNameSize << 1:bytesAvailable;
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // stick it in the heap buffer
+                bufPtr.Zero();
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == iFileNameSize )
+                    {
+                    // If filename is now read, start reading the file content.
+                    iRestoreState = ERestoreExpectData;
+                    }
+                else
+                    {
+                    // Otherwise, continue reading the file.
+                    iRestoreState = ERestoreExpectMoreFileName;
+                    }
+                break;
+                }
+            // the file name overran the buffer
+            case ERestoreExpectMoreFileName:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // Check how many more bytes do we want.
+                TInt bytesNeeded = ( iFileNameSize  -bufPtr.Length() ) << 1;
+                TInt bytesToGet = bytesAvailable >= bytesNeeded ? bytesNeeded : bytesAvailable;
+                TPtrC8 ptr8 = aBuffer.Mid( bufferIndex, bytesToGet );
+                bufferIndex += bytesToGet;
+
+                // convert to 16 bit
+                TPtr ptr16(
+                    (TUint16*) ptr8.Ptr(),
+                    bytesToGet >> 1,
+                    bytesToGet >> 1 );
+
+                // append it to the heap buffer
+                bufPtr.Append( ptr16 );
+
+                if( bufPtr.Length() == iFileNameSize )
+                    {
+                    // If filename is now read, start reading the file content.
+                    iRestoreState = ERestoreExpectData;
+                    }
+                else
+                    {
+                    // same state ERestoreExpectMoreFileName;
+                    }
+                break;
+                }
+            // now for the data
+            case ERestoreExpectData:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                iFileOpenError = EFalse;
+                // iFileSize counts down
+                TInt bytesToGet = bytesAvailable >= iFileSize ? iFileSize : bytesAvailable;
+
+                if ( iFsSession.IsValidName( bufPtr ) &&
+                     !AknsSrvUtils::IsFile( iFsSession, bufPtr ) &&
+                     RestoreFileInPrivateDirectoryL( bufPtr ) == KErrNone )
+                    {
+                    // write it
+                    TInt fileErr = iFile.Write( aBuffer.Mid( bufferIndex, bytesToGet ) );
+                    AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL file write %d", fileErr );
+                    }
+                else
+                    {
+                    iFileOpenError = ETrue;
+                    }
+
+                // update our counters
+                bufferIndex += bytesToGet;
+                iFileSize -= bytesToGet;
+
+                // Check if finished now.
+                if( iFileSize == 0 )
+                    {
+                    // If file is now written, restore is complete (for this file).
+                    iRestoreState = ERestoreComplete;
+                    }
+                else
+                    {
+                    // Otherwise, continue reading and writing the file.
+                    iRestoreState = ERestoreExpectMoreData;
+                    }
+                if ( iFileOpenError )
+                    {
+                    return;
+                    }
+
+                break;
+                }
+            // will almost certainly exceed a single buffer
+            case ERestoreExpectMoreData:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // Check how much more.
+                TInt bytesToGet = bytesAvailable >= iFileSize ? iFileSize : bytesAvailable;
+
+                // write it
+                if (!iFileOpenError)
+                    {
+                    TInt fileErr = iFile.Write( aBuffer.Mid( bufferIndex, bytesToGet ) );
+                    AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL file write %d", fileErr );
+                    }
+
+                // update the counters
+                bufferIndex += bytesToGet;
+                iFileSize -= bytesToGet;
+
+                // Check if finished now.
+                if( iFileSize == 0 )
+                    {
+                    // If file is now written, restore is complete (for this file).
+                    iRestoreState = ERestoreComplete;
+                    }
+                else
+                    {
+                    // same state ERestoreExpectMoreData;
+                    }
+                break;
+                }
+            // file completely restored
+            case ERestoreComplete:
+                {
+                AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL state %d", iRestoreState );
+                // calculate the checksum
+                if(!iFileOpenError)
+                    {
+                    TUint64 cksum = CheckSumL( iFile ) & 0xffffffff;
+
+                    // validate that the checksum matches
+                    if( cksum != iChecksum )
+                        {
+                        AKNS_TRACE_DEBUG2("CAknsSrvActiveBackupDataClient::RestoreBaseDataSectionL checksum fail %d %d", cksum, iChecksum );
+                        User::Leave( KErrCorrupt );
+                        }
+
+                    // Done with the file, so close it.
+                    iFile.Close();
+                    }
+                iFilesRestored++;
+
+                // end of data - Check if another file is to be restored.
+                iRestoreState = ERestoreNumberOfFiles;
+                iFileOpenError = EFalse;
+
+                // Each file should end at the end of buffer.
+                aFinished = ETrue;
+                return;
+                }
+            default:
+                break;
+            }
+        } while(!done);
+    }
+
+// ---------------------------------------------------------------------------
+// Incremental restoration is not supported.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::InitialiseRestoreIncrementDataL(
+    TDriveNumber /*aDrive*/)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseRestoreIncrementDataL" );
+    User::Leave( KErrNotSupported );
+    }
+
+// ---------------------------------------------------------------------------
+// Incremental restoration is not supported.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::RestoreIncrementDataSectionL(
+    TDesC8& /*aBuffer*/, TBool /*aFinished*/)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreIncrementDataSectionL" );
+    User::Leave( KErrNotSupported );
+    }
+
+// ---------------------------------------------------------------------------
+// Called when restore is complete - sets data back to initial state.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::RestoreComplete(TDriveNumber /*aDrive*/)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreComplete" );
+    // Possibly delete some extra data.
+    iDataRestored = EFalse;
+    iRestoreState = ERestoreNumberOfFiles;
+    }
+
+// ---------------------------------------------------------------------------
+// Tidy up when operation is over.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::TerminateMultiStageOperation()
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::TerminateMultiStageOperation" );
+    iFileArray.Reset();
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TUint CAknsSrvActiveBackupDataClient::GetDataChecksum(TDriveNumber /*aDrive*/)
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::GetDataChecksum" );
+    // not required - not implemented
+    return KArbitraryNumber;
+    }
+
+// ---------------------------------------------------------------------------
+// Initialize backup.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::InitialiseGetProxyBackupDataL(
+    TSecureId /*aSID*/, TDriveNumber aDrive )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseGetProxyBackupDataL" );
+    DoInitialiseGetBackupDataL( aDrive );
+    }
+
+// ---------------------------------------------------------------------------
+// Initializes restore state machine.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::InitialiseRestoreProxyBaseDataL(
+    TSecureId /*aSID*/, TDriveNumber /*aDrive*/ )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::InitialiseRestoreProxyBaseDataL" );
+    // this is the first state of the restore state machine
+    iRestoreState = ERestoreNumberOfFiles;
+    // to keep track in the state machine whether any data was actually sent
+    iDataRestored = EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// Creates a checksum for the files.
+// ---------------------------------------------------------------------------
+//
+TUint64 CAknsSrvActiveBackupDataClient::CheckSumL(const RFile& aOpenFile) const
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::CheckSumL" );
+    // scoot through the database file building the checksum
+    TInt seekPos = 0; // rewind first
+    User::LeaveIfError( aOpenFile.Seek( ESeekStart, seekPos ) );
+    TUint64 total = 0;
+    HBufC8* block = HBufC8::NewL( KCheckSumBlockSize );
+    CleanupStack::PushL( block );
+    TPtr8 ptr=block->Des();
+    while( ETrue )
+        {
+        User::LeaveIfError( aOpenFile.Read( ptr ) );
+        TInt len = ptr.Length();
+        if( len == 0 )
+            {
+            break;
+            }
+        // calculate the checksum
+        for( TInt i = 0; i < len; ++i )
+            {
+            TUint64 carry = total&(0x8000000000000000ULL);
+            total<<=1;
+            if( carry )
+                {
+                total|=1;
+                }
+            TUint in = ptr[i];
+            total += in;
+            }
+        };
+    CleanupStack::PopAndDestroy( block );
+    // restore file position
+    seekPos = 0;
+    User::LeaveIfError( aOpenFile.Seek( ESeekStart, seekPos ) );
+    return total;
+    }
+
+// ---------------------------------------------------------------------------
+// Scan directory for files.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::ScanDirectoryForSkinFilesL(
+    const TDesC& aRootDir )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::ScanDirectoryForSkinFilesL" );
+    CDirScan *dirScan = CDirScan::NewLC( iFsSession );
+    dirScan->SetScanDataL(
+        aRootDir,
+        KEntryAttNormal | KEntryAttHidden | KEntryAttSystem |
+        KEntryAttDir,
+        ESortNone );
+
+    // Fetch all directories and files from root.
+    CDir* entryList = NULL;
+    TParse parse;
+    for(;;)
+        {
+        TRAPD( err, dirScan->NextL( entryList ) );
+
+        // Stop in error case, or if no more data.
+        if (!entryList  || ( err != KErrNone) )
+            {
+            break;
+            }
+
+        for (TInt i=0; i < entryList->Count(); i++)
+            {
+            TEntry entry = (*entryList)[i];
+            const TDesC& dir = dirScan->FullPath();
+            parse.Set( entry.iName, &dir, NULL );
+            if ( !entry.IsDir() )
+                {
+                iFileArray.Append( parse );
+                }
+            }
+        delete entryList;
+        }
+    AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::ScanDirectoryForSkinFilesL noFiles=%d", iFileArray.Count() );
+
+    // Destroy the list.
+    CleanupStack::PopAndDestroy( dirScan );
+    }
+
+// ---------------------------------------------------------------------------
+// Re-creates backed-up file in private directory.
+// ---------------------------------------------------------------------------
+//
+TInt CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL(
+    const TDesC& aFileName )
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL" );
+    _LIT( KAknsStaticPath, "\\private\\10207114\\import" );
+    _LIT( KAknsSknExtension, ".SKN" );
+    TBool parseError = EFalse;
+    TInt fileErr = KErrNone;
+
+    HBufC* fileNameBuffer = HBufC::NewL( KMaxFileName );
+    TParsePtrC fileName( aFileName );
+    TPtr bufferPtr = fileNameBuffer->Des();
+
+    // First append drive and static path.
+    if ( fileName.DrivePresent() )
+        {
+        bufferPtr.Append( fileName.Drive() );
+        }
+    else
+        {
+        AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse error1" );
+        parseError = ETrue;
+        }
+    if ( !parseError )
+        {
+        bufferPtr.Append( KAknsStaticPath );
+        }
+
+    if ( fileName.PathPresent() && !parseError )
+        {
+        // Take path without the trailing backslash.
+        TPtrC path = fileName.Path().Left( fileName.Path().Length() - 1 );
+
+        // Locate last backslash.
+        TChar backslash('\\');
+        TInt bsLoc = path.LocateReverse( backslash );
+
+        // Append skin PID to the directory.
+        bufferPtr.Append( fileName.Path().Mid( bsLoc ) );
+
+        if ( fileName.ExtPresent() )
+            {
+            // Last, append filename. Now string is complete.
+            bufferPtr.Append( fileName.NameAndExt() );
+
+            // switch the extension and check for file existance.
+            bufferPtr.Replace(
+                bufferPtr.Length() - KExtensionLength,
+                KExtensionLength,
+                KAknsSknExtension );
+            if ( !AknsSrvUtils::IsFile( iFsSession, bufferPtr ) )
+                {
+                // There is no matching .skn-file, do not restore the graphics file.
+                fileErr = KErrNotFound;
+                }
+
+            // switch back the graphics file extension.
+            bufferPtr.Replace(
+                bufferPtr.Length() - KExtensionLength,
+                KExtensionLength,
+                fileName.Ext() );
+            }
+        else
+            {
+            AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse error2" );
+            parseError = ETrue;
+            }
+        }
+    else
+        {
+        AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse error3" );
+        parseError = ETrue;
+        }
+
+    if( !parseError && fileErr == KErrNone )
+        {
+        if ( AknsSrvUtils::IsFile( iFsSession, bufferPtr ) )
+            {
+            // Do not restore, if the file already exists.
+            fileErr = KErrAlreadyExists;
+            }
+        else
+            {
+            // Create the file.
+            fileErr = iFile.Replace(
+                iFsSession,
+                bufferPtr,
+                ( EFileWrite | EFileShareExclusive | EFileStream ) );
+            }
+        }
+
+    AKNS_TRACE_DEBUG1("CAknsSrvActiveBackupDataClient::RestoreFileInPrivateDirectoryL parse ret=%d", fileErr );
+    if ( fileErr != KErrNone )
+        {
+        // If error creating or parsing the file, skip to next one.
+        return fileErr;
+        }
+    if ( parseError )
+        {
+        return KErrArgument;
+        }
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// C++ constructor.
+// ---------------------------------------------------------------------------
+//
+CAknsSrvActiveBackupDataClient::CAknsSrvActiveBackupDataClient(
+    RFs& aFsSession ) : iFsSession( aFsSession )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// 2nd phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::ConstructL()
+    {
+    AKNS_TRACE_DEBUG("CAknsSrvActiveBackupDataClient::ConstructL" );
+    iBuffer=HBufC::NewL( KMaxHeaderSize );
+    }
+
+// ---------------------------------------------------------------------------
+// Do initialise get backup data.
+// ---------------------------------------------------------------------------
+//
+void CAknsSrvActiveBackupDataClient::DoInitialiseGetBackupDataL(
+    TDriveNumber aDrive )
+    {
+    // this is the index of the file being processed - point to the beginning
+    iFileIndex=0;
+    // the first state of the backup state machine
+    iBackupState=EBackupNoFileOpen;
+
+    TFileName path;
+    TChar driveLetter;
+    RFs::DriveToChar( aDrive, driveLetter );
+    path.Append( driveLetter );
+    path.Append( KSkinRootDir );
+    // Store the directories and filenames.
+    ScanDirectoryForSkinFilesL( path );
+    }
+
+// End of file