--- /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