deviceencryption/DevEncUi/src/DevEncUiAppui.cpp
branchRCL_3
changeset 38 491b3ed49290
parent 36 95243422089a
child 39 65326cf895ed
equal deleted inserted replaced
36:95243422089a 38:491b3ed49290
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0""
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of CDevEncUiAppUi.
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include <avkon.hrh>
       
    20 #include <centralrepository.h>
       
    21 #include <devencui.rsg>
       
    22 #include <csxhelp/devenc.hlp.hrh>
       
    23 #include <e32event.h>
       
    24 #include <hlplch.h> // Help launcher
       
    25 #include <StringLoader.h> // TBD: Needed?
       
    26 #include <w32std.h>
       
    27 #include <DevEncExternalCRKeys.h>
       
    28 
       
    29 #include "DevEncLog.h"
       
    30 #include "DevEnc.hrh"
       
    31 #include "DevEncUi.pan"
       
    32 #include "DevEncUiAppui.h"
       
    33 #include "DevEncUiEncrView.h"
       
    34 #include "DevEncUiEncryptionOperator.h"
       
    35 #include "DevEncUiDecrView.h"
       
    36 
       
    37 #include "DevEncUiMainView.h"
       
    38 #include "DevEncUiMemoryEntity.h"
       
    39 #include "DevEncUids.hrh"
       
    40 
       
    41 #include <AknGlobalNote.h>
       
    42 
       
    43 //Local definitions
       
    44 const TInt KDevEncUiConstructionDelay( 1000000 );
       
    45 
       
    46 // ============================ MEMBER FUNCTIONS ===============================
       
    47 
       
    48 // --------------------------------------------------------------------------
       
    49 // CDevEncUiAppUi::ConstructL()
       
    50 // Symbian 2nd phase constructor can leave.
       
    51 // --------------------------------------------------------------------------
       
    52 //
       
    53 void CDevEncUiAppUi::ConstructL()
       
    54     {
       
    55     // Initialise app UI with standard value.
       
    56     BaseConstructL( EAknEnableSkin | EAknSingleClickCompatible );
       
    57 
       
    58     DFLOG( ">>CDevEncUiAppUi::ConstructL" );
       
    59 
       
    60     User::LeaveIfError( iFs.Connect() );
       
    61 
       
    62     DFLOG( "CDevEncUiAppUi::ConstructL => Create drive path" );
       
    63     // Create private folder. TBD: Needed?
       
    64     TInt error = iFs.CreatePrivatePath( EDriveC );
       
    65     if ( error == KErrAlreadyExists )
       
    66         {
       
    67         error = KErrNone;
       
    68         }
       
    69     DFLOG( "CDevEncUiAppUi::ConstructL => Leave ?" );
       
    70     User::LeaveIfError( error );
       
    71     DFLOG( "CDevEncUiAppUi::ConstructL => No, constructing CR" );
       
    72 
       
    73     // Central repository settings
       
    74     iCrSettings = CRepository::NewL( TUid::Uid( KCRDevEncUiSettings ) );
       
    75     DFLOG( "CDevEncUiAppUi::ConstructL => Adding observer" );
       
    76 
       
    77     // Create MMC observer
       
    78     iObserver = CMmcObserver::NewL( this, &iFs );
       
    79     iObserver->StartObserver();
       
    80 
       
    81     // Call the MMC callback function once to get the initial card status
       
    82     MMCStatusChangedL();
       
    83 
       
    84     DFLOG( "CDevEncUiAppUi::ConstructL => constructing mass memory" );
       
    85     
       
    86     CDevEncUiMemoryEntity* massMemory = CDevEncUiMemoryEntity::NewLC( iEikonEnv, 
       
    87     		                                                            EPhoneMemory );
       
    88     
       
    89     DFLOG( "CDevEncUiAppUi::ConstructL => adding to mem entities" );
       
    90     iMemEntities.AppendL( massMemory );
       
    91     CleanupStack::Pop( massMemory );
       
    92     
       
    93     DFLOG( "CDevEncUiAppUi::ConstructL => constructing memory card" );
       
    94     
       
    95     CDevEncUiMemoryEntity* memoryCard = CDevEncUiMemoryEntity::NewLC( iEikonEnv,
       
    96         		                                                        EMemoryCard );
       
    97     
       
    98     DFLOG( "CDevEncUiAppUi::ConstructL => adding to mem entities" );
       
    99     iMemEntities.AppendL( memoryCard );
       
   100     CleanupStack::Pop( memoryCard );
       
   101 
       
   102     DFLOG( "CDevEncUiAppUi::ConstructL => constructing phone memory" );
       
   103 
       
   104     CDevEncUiMemoryEntity* phoneMemory = CDevEncUiMemoryEntity::NewLC( iEikonEnv,
       
   105                                                                        EPrimaryPhoneMemory );
       
   106     
       
   107     DFLOG( "CDevEncUiAppUi::ConstructL => adding to mem entities" );
       
   108     iMemEntities.AppendL( phoneMemory );
       
   109     CleanupStack::Pop( phoneMemory );
       
   110 
       
   111     DFLOG( "CDevEncUiAppUi::ConstructL() => Create enc operator" );
       
   112 
       
   113     // Create encryption operator
       
   114     iEncOperator = CDevEncUiEncryptionOperator::NewL( *iEikonEnv,
       
   115                                                       *this,
       
   116                                                       iCrSettings );
       
   117 
       
   118     DFLOG( "CDevEncUiAppUi::ConstructL() => Create views" );
       
   119 
       
   120     // Create views
       
   121     iMainView = CDevEncUiMainView::NewL( iMemEntities,
       
   122                                          iCrSettings,
       
   123                                          iMmcStatus );
       
   124 
       
   125     AddViewL( iMainView ); // transfer ownership
       
   126 
       
   127     iEncryptionView = CDevEncUiEncrView::NewL( iMemEntities );
       
   128     AddViewL( iEncryptionView ); // transfer ownership
       
   129 
       
   130     iDecryptionView = CDevEncUiDecrView::NewL( iMemEntities );
       
   131     AddViewL( iDecryptionView ); // transfer ownership
       
   132 
       
   133     SetDefaultViewL( *iMainView );
       
   134     
       
   135     DFLOG( "ConstructL 6" );
       
   136 
       
   137     iConstructionOnGoing = ETrue;
       
   138     
       
   139     iTimer = CDevEncUiTimer::NewL( this );
       
   140     iTimer->After( KDevEncUiConstructionDelay );
       
   141 
       
   142     DFLOG( "<<CDevEncUiAppUi::ConstructL" );
       
   143     }
       
   144 
       
   145 // --------------------------------------------------------------------------
       
   146 // CDevEncUiAppUi::CDevEncUiAppUi()
       
   147 // C++ default constructor can NOT contain any code, that might leave.
       
   148 // --------------------------------------------------------------------------
       
   149 //
       
   150 CDevEncUiAppUi::CDevEncUiAppUi()
       
   151     {
       
   152     // No implementation required
       
   153     }
       
   154 
       
   155 // --------------------------------------------------------------------------
       
   156 // CDevEncUiAppUi::~CDevEncUiAppUi()
       
   157 // Destructor.
       
   158 // --------------------------------------------------------------------------
       
   159 //
       
   160 CDevEncUiAppUi::~CDevEncUiAppUi()
       
   161     {
       
   162     DFLOG( ">>CDevEncUiAppUi::~CDevEncUiAppUi" );
       
   163     delete iObserver;
       
   164     iFs.Close();
       
   165     delete iEncOperator;
       
   166     if (iMemEntities.Count())
       
   167         iMemEntities[ EMemoryCard ]->RemoveObserver( this );
       
   168     for ( TInt i = 0; i < iMemEntities.Count(); i++ )
       
   169         {
       
   170         delete iMemEntities[i];
       
   171         }
       
   172     iMemEntities.Close();
       
   173     delete iCrSettings;
       
   174     delete iTimer;
       
   175     }
       
   176 
       
   177 // --------------------------------------------------------------------------
       
   178 // CDevEncUiAppUi::HandleCommandL()
       
   179 // Takes care of command handling.
       
   180 // --------------------------------------------------------------------------
       
   181 //
       
   182 void CDevEncUiAppUi::HandleCommandL( TInt aCommand )
       
   183     {
       
   184     DFLOG( ">>CDevEncUiAppUi::HandleCommandL" );
       
   185 
       
   186     switch( aCommand )
       
   187         {
       
   188         // These commands are specific to the memory card
       
   189         case EDevEncUiCommandEncryptWithoutSavingKey: // fall through
       
   190         case EDevEncUiCommandEncryptAndSaveKey:
       
   191         case EDevEncUiCommandEncryptWithRestoredKey:
       
   192             {
       
   193             // Pass the MMC memory entity to the operator, along with the command
       
   194             iEncOperator->HandleMmcEncryptRequestL( iMemEntities[ EMemoryCard ],
       
   195                                                     aCommand );
       
   196             break;
       
   197             }
       
   198 
       
   199         case EDevEncUiCommandDecrypt: // fall through
       
   200         case EDevEncUiCommandDecryptAndTurnOffEncryption:
       
   201             {
       
   202             // Pass the MMC memory entity to the operator, along with the command
       
   203             iEncOperator->HandleMmcDecryptRequestL( iMemEntities[ EMemoryCard ],
       
   204                                                     aCommand );
       
   205             break;
       
   206             }
       
   207 
       
   208         case EDevEncUiCommandHelp:
       
   209             {
       
   210             DisplayHelpL();
       
   211             break;
       
   212             }
       
   213 
       
   214         case EAknSoftkeyBack:
       
   215             {
       
   216             // Get the current view
       
   217             TVwsViewId wsViewId;
       
   218             TInt err = GetActiveViewId( wsViewId );
       
   219             if ( ( err != KErrNone ) ||
       
   220                  ( wsViewId.iAppUid.iUid != KDevEncUiUid ) )
       
   221                 {
       
   222                 User::Leave( err );
       
   223                 }
       
   224 
       
   225             // Go to the main view from the encryption and decryption views
       
   226             if ( wsViewId.iViewUid.iUid == EDevEncUiEncrViewId ||
       
   227                  wsViewId.iViewUid.iUid == EDevEncUiDecrViewId )
       
   228                 {
       
   229                 ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
       
   230                 }
       
   231             if ( wsViewId.iViewUid.iUid == EDevEncUiMainViewId )
       
   232             	{
       
   233             	Exit();
       
   234             	}
       
   235             break;
       
   236             }
       
   237 
       
   238         case EEikCmdExit: // fall through
       
   239         case EAknSoftkeyExit:
       
   240             {
       
   241             Exit();
       
   242             break;
       
   243             }
       
   244 
       
   245         default:
       
   246             Panic( EDevEncUi );
       
   247             break;
       
   248         }
       
   249     }
       
   250 
       
   251 // --------------------------------------------------------------------------
       
   252 // Called by the framework when the app is moved to or from foreground.
       
   253 //
       
   254 // --------------------------------------------------------------------------
       
   255 //
       
   256 void CDevEncUiAppUi::HandleForegroundEventL( TBool aForeground )
       
   257     {
       
   258     DFLOG( "CDevEncUiAppUi::HandleForegroundEventL" );
       
   259     DFLOG2( "CDevEncUiAppUi::HandleForegroundEventL => aForeground = %d ", aForeground );
       
   260     CAknAppUi::HandleForegroundEventL( aForeground );
       
   261     
       
   262     iForeground = aForeground;
       
   263     
       
   264     if( iConstructionOnGoing )
       
   265         {
       
   266         DFLOG( "CDevEncUiAppUi::HandleForegroundEventL => Construction on going" );
       
   267         if( iTimer )
       
   268         	{
       
   269         	iTimer->Cancel();
       
   270             }
       
   271         iTimer->After( KDevEncUiConstructionDelay );
       
   272         }
       
   273     }
       
   274 
       
   275 // --------------------------------------------------------------------------
       
   276 // Called by the framework before the options menu is shown.
       
   277 // Sets the correct menu items.
       
   278 // --------------------------------------------------------------------------
       
   279 //
       
   280 void CDevEncUiAppUi::DynInitMenuPaneL( TInt /*aResourceId*/,
       
   281                                        CEikMenuPane* /*aMenuPane*/ )
       
   282     {
       
   283     }
       
   284 
       
   285 // --------------------------------------------------------------------------
       
   286 // Called by the framework before the context-sensitive help is shown.
       
   287 // Sets the correct menu items.
       
   288 // --------------------------------------------------------------------------
       
   289 //
       
   290 //CArrayFix<TCoeHelpContext>* CDevEncUiAppUi::HelpContextL()
       
   291 //    {
       
   292 //    TCoeHelpContext& aContext
       
   293 //    }
       
   294 
       
   295 // --------------------------------------------------------------------------
       
   296 // Called by the framework before the context-sensitive help is shown.
       
   297 // Sets the correct menu items.
       
   298 // --------------------------------------------------------------------------
       
   299 void CDevEncUiAppUi::DisplayHelpL()
       
   300     {
       
   301     CArrayFix<TCoeHelpContext>* contexts = 
       
   302         new ( ELeave ) CArrayFixFlat<TCoeHelpContext>( 1 );
       
   303     CleanupStack::PushL( contexts );
       
   304     TCoeHelpContext context;
       
   305     context.iMajor = TUid::Uid( KDevEncUiUid );
       
   306 
       
   307     // Get the currently active view
       
   308     TVwsViewId wsViewId;
       
   309     TInt err = GetActiveViewId( wsViewId );
       
   310     if ( ( err != KErrNone ) ||
       
   311          ( wsViewId.iAppUid.iUid != KDevEncUiUid ) )
       
   312         {
       
   313         User::Leave( err );
       
   314         }
       
   315     
       
   316     // Set the help context for the current view
       
   317     switch ( wsViewId.iViewUid.iUid )
       
   318         {
       
   319         case EDevEncUiEncrViewId:
       
   320             {
       
   321             context.iContext = KES_HLP_ENCRYPTION_ENCRYPT;
       
   322             }
       
   323             break;
       
   324         case EDevEncUiDecrViewId:
       
   325             {
       
   326             context.iContext = KES_HLP_ENCRYPTION_DECRYPT;
       
   327             }
       
   328             break;
       
   329         default: // Main view
       
   330             {
       
   331             context.iContext = KES_HLP_ENCRYPTION_MAIN;
       
   332             }
       
   333             break;
       
   334         }
       
   335  
       
   336     contexts->AppendL( context );
       
   337     CleanupStack::Pop( contexts ); 
       
   338     HlpLauncher::LaunchHelpApplicationL( iCoeEnv->WsSession(), contexts );              
       
   339     }
       
   340 
       
   341 // --------------------------------------------------------------------------
       
   342 // Called by CDevEncMmcObserver when MMC status changes.
       
   343 // 
       
   344 // --------------------------------------------------------------------------
       
   345 void CDevEncUiAppUi::MMCStatusChangedL()
       
   346     {
       
   347     DFLOG( "CDevEncUiAppUi::MMCStatusChangedL" );
       
   348     TVolumeInfo volInfo;
       
   349 
       
   350     TInt err = iFs.Volume( volInfo, /*EDriveE*/EDriveF );
       
   351     switch ( err )
       
   352         {
       
   353         case KErrNone:
       
   354             {
       
   355             // Readable MMC inserted
       
   356             DFLOG( "MMC inserted" );
       
   357             iMmcStatus = EMmcOk;
       
   358             break;
       
   359             }
       
   360 
       
   361         case KErrNotReady:
       
   362             {
       
   363             // MMC ejected
       
   364             DFLOG( "MMC ejected" );
       
   365             iMmcStatus = EMmcNotPresent;
       
   366             break;
       
   367             }
       
   368 
       
   369         case KErrCorrupt:
       
   370             {
       
   371             // Corrupt or unformatted MMC, or wrong key
       
   372             DFLOG( "MMC corrupt, unformatted or encrypted with other key" );
       
   373             iMmcStatus = EMmcNotReadable;
       
   374             break;
       
   375             }
       
   376 
       
   377         default:
       
   378             {
       
   379             DFLOG2( "RFs::Volume returned error %d", err );
       
   380             break;
       
   381             }
       
   382         } // switch
       
   383     }
       
   384 
       
   385 // --------------------------------------------------------------------------
       
   386 // Called by memory entity when memory status changes.
       
   387 // 
       
   388 // --------------------------------------------------------------------------
       
   389 void CDevEncUiAppUi::UpdateInfo( TDevEncUiMemoryType aType,
       
   390                                  TUint aState,
       
   391                                  TUint /*aProgress*/ )
       
   392     {
       
   393     DFLOG( "CDevEncUiAppUi::UpdateInfo" );
       
   394     TInt error( KErrNone );
       
   395     TRAP( error, DoUpdateInfoL( aType, aState ) );
       
   396     DFLOG2( "CDevEncUiAppUi::DoUpdateInfo returned %d", error );
       
   397     }
       
   398 
       
   399 // --------------------------------------------------------------------------
       
   400 // Helper function called by UpdateInfo when memory status changes.
       
   401 // 
       
   402 // --------------------------------------------------------------------------
       
   403 void CDevEncUiAppUi::DoUpdateInfoL( TDevEncUiMemoryType aType,
       
   404                                     TUint aState )
       
   405     {
       
   406     DFLOG( ">>CDevEncUiAppUi::DoUpdateInfoL" );
       
   407     if ( aType != EMemoryCard )
       
   408         {
       
   409         return;
       
   410         }
       
   411 
       
   412     // Prevent re-entry
       
   413     if ( iStatusUpdateOngoing )
       
   414         {
       
   415         return;
       
   416         }
       
   417     iStatusUpdateOngoing = ETrue;
       
   418 
       
   419     DFLOG3( "CDevEncUiAppUi::DoUpdateInfoL, type %d, state %d",
       
   420             aType, aState );
       
   421     DFLOG2( "Mmc state %d", iMmcStatus );
       
   422     DFLOG2( "Enc state %d", iMmcEncState );
       
   423     
       
   424     // Check encryption key status
       
   425     TInt mmcKeyInDriver( 0 );
       
   426     iCrSettings->Get( KDevEncUserSettingMemoryCard, mmcKeyInDriver );
       
   427     
       
   428     if ( ( iMmcStatus == EMmcOk ) && 
       
   429          ( iMmcEncState == EUnmounted ) &&
       
   430          ( aState == EDecrypted ) )
       
   431         {
       
   432         // A readable memory card has just been inserted
       
   433     
       
   434         if ( mmcKeyInDriver )
       
   435             {
       
   436             // We have a valid encryption key, but the newly inserted
       
   437             // card is decrypted. Ask if the user wants to encrypt.
       
   438             // (see UI spec 2.13)
       
   439             iEncOperator->SuggestMmcEncryptionL(
       
   440                                            iMemEntities[ EMemoryCard ] );
       
   441             }
       
   442         }
       
   443 
       
   444     if ( ( iMmcStatus == EMmcNotReadable ) && 
       
   445          ( iMmcEncState == EUnmounted ) &&
       
   446          ( aState == ECorrupted ) )
       
   447         {
       
   448         // An unreadable memory card has just been inserted
       
   449         
       
   450         if ( mmcKeyInDriver )
       
   451             {
       
   452             // We seem to have the wrong encryption key in the driver.
       
   453             // Inform the user that the card cannot be used.
       
   454             // (see UI spec 2.16)
       
   455             iEncOperator->ErrorNoteL(
       
   456                             R_DEVENCUI_TEXT_NOTE_INSERTON_UNUSEDMEMORYCARD );
       
   457             }
       
   458         else
       
   459             {
       
   460             DFLOG( "CDevEncUiAppUi::DoUpdateInfoL => SuggestMmcDecryption" );
       
   461             // We have no encryption key in the driver.
       
   462             // Ask if the user wants to import a key and decrypt.
       
   463             // (see UI spec 2.17)
       
   464             iEncOperator->SuggestMmcDecryptionL(
       
   465                                        iMemEntities[ EMemoryCard ] );
       
   466             }
       
   467         }
       
   468 
       
   469     iMmcEncState = aState;
       
   470     iStatusUpdateOngoing = EFalse;
       
   471     DFLOG( "<<CDevEncUiAppUi::DoUpdateInfoL" );
       
   472     }
       
   473 
       
   474 // --------------------------------------------------------------------------
       
   475 // Called by the CDevEncUiTimer when the event is generated.
       
   476 // 
       
   477 // --------------------------------------------------------------------------
       
   478 void CDevEncUiAppUi::Timeout()
       
   479 	{
       
   480 	DFLOG( "CDevEncUiAppUi::Timeout()" );	
       
   481 	
       
   482 	if( iForeground )
       
   483 		{
       
   484 		DFLOG( "CDevEncUiAppUi::Timeout() => Construction completed" );
       
   485 		//the construction is completed now
       
   486 		iConstructionOnGoing = EFalse;
       
   487 		// This class needs to observe memory card status changes.
       
   488         // (This call results in a call to UpdateInfo, hence we need to be fully
       
   489         // constructed before this.)
       
   490 	    TRAP_IGNORE(iMemEntities[ EMemoryCard ]->AddObserverL( this ));
       
   491 	    
       
   492 		}
       
   493 	}
       
   494 
       
   495 // -----------------------------------------------------------------------------
       
   496 // CDevEncUiAppUi::ProcessCommandParametersL
       
   497 // From CEikAppUi
       
   498 // -----------------------------------------------------------------------------
       
   499 //
       
   500 TBool CDevEncUiAppUi::ProcessCommandParametersL(
       
   501     TApaCommand /*aCommand*/,
       
   502     TFileName& /*aDocumentName*/,
       
   503     const TDesC8& /*aTail*/ )
       
   504     {
       
   505     return ETrue;
       
   506     }
       
   507 
       
   508 // -----------------------------------------------------------------------------
       
   509 // CDevEncUiAppUi::OpenFileL
       
   510 // -----------------------------------------------------------------------------
       
   511 //
       
   512 void CDevEncUiAppUi::OpenFileL(const TDesC& /*aFilename*/)
       
   513     {
       
   514     DFLOG("CDevEncUiAppUi::OpenFileL");
       
   515     }
       
   516 
       
   517 // -----------------------------------------------------------------------------
       
   518 // CDevEncUiAppUi::OpenFileL()
       
   519 // -----------------------------------------------------------------------------
       
   520 //
       
   521 void CDevEncUiAppUi::OpenFileL(RFile& aFile)
       
   522     {
       
   523     _LIT(KTargetDir,"c:\\data\\others\\");
       
   524     TBuf16<100> destinationPath;
       
   525     destinationPath.Copy( KTargetDir );
       
   526     TBuf16<250> sourcePath;
       
   527     aFile.FullName( sourcePath );
       
   528     
       
   529     // if the paths are the same, the copy operation will not be executed
       
   530     if ( sourcePath.Left( destinationPath.Length() ).CompareF( destinationPath ) )
       
   531     	{
       
   532         // copy the file to Others folder
       
   533         TRAPD(err, CopyL( sourcePath, destinationPath ));
       
   534     
       
   535         if( err == KErrNone )
       
   536             {
       
   537             iEncOperator->InfoNoteL( R_DEVENCUI_TEXT_NOTE_SAVEINFO, ETrue );
       
   538             ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
       
   539             }
       
   540         else
       
   541     	    {
       
   542             Exit();
       
   543     	    }
       
   544     	}
       
   545     else
       
   546     	{
       
   547     	ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
       
   548     	}
       
   549 	}
       
   550 
       
   551 // -----------------------------------------------------------------------------
       
   552 // CDevEncUiAppUi::Copy()
       
   553 // -----------------------------------------------------------------------------
       
   554 //
       
   555 void CDevEncUiAppUi::CopyL(const TDesC &anOld, const TDesC &aNew)
       
   556 	{   
       
   557 	CFileMan* fileMan=CFileMan::NewL( iFs );
       
   558 	CleanupStack::PushL( fileMan );
       
   559  
       
   560 	User::LeaveIfError(fileMan->Copy( anOld, aNew ));
       
   561  
       
   562 	CleanupStack::PopAndDestroy( fileMan );
       
   563 	}
       
   564 
       
   565 // End of File