Load from LastGood if the main profile is tampered/corrupt.

Don't write new data on a load fail - it doesn't give the user a change to correct the load failure.
This commit is contained in:
Chris Danford
2004-10-07 19:57:51 +00:00
parent c47b7fb124
commit 5c5ac50b82
5 changed files with 81 additions and 82 deletions
+19 -12
View File
@@ -563,11 +563,8 @@ void Profile::IncrementCategoryPlayCount( StepsType st, RankingCategory rc )
XNode* X = xml.GetChild(#X); \
if( X==NULL ) LOG->Warn("Failed to read section " #X); \
else Load##X##FromNode(X); }
int g_iOnceCtr;
#define FOR_ONCE for(g_iOnceCtr=0;g_iOnceCtr<1;g_iOnceCtr++)
bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
Profile::LoadResult Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
{
CHECKPOINT;
@@ -581,7 +578,7 @@ bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
// Check for the existance of stats.xml
CString fn = sDir + STATS_XML;
if( !IsAFile(fn) )
return true; // This is a common case and not a load error, so return success.
return failed_no_profile;
//
// Don't unreasonably large stats.xml files.
@@ -592,7 +589,7 @@ bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
if( iBytes > MAX_PLAYER_STATS_XML_SIZE_BYTES )
{
LOG->Warn( "The file '%s' is unreasonably large. It won't be loaded.", fn.c_str() );
return false; // error
return failed_tampered;
}
}
@@ -606,7 +603,7 @@ bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
if( !CryptManager::VerifyFileWithFile(sStatsXmlSigFile, sDontShareFile) )
{
LOG->Warn( "The don't share check for '%s' failed. Data will be ignored.", sStatsXmlSigFile.c_str() );
return false; // error
return failed_tampered;
}
LOG->Trace( "Done." );
@@ -615,7 +612,7 @@ bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
if( !CryptManager::VerifyFileWithFile(fn, sStatsXmlSigFile) )
{
LOG->Warn( "The signature check for '%s' failed. Data will be ignored.", fn.c_str() );
return false; // error
return failed_tampered;
}
LOG->Trace( "Done." );
}
@@ -625,19 +622,19 @@ bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
if( !xml.LoadFromFile( fn ) )
{
LOG->Warn( "Couldn't open file '%s' for reading.", fn.c_str() );
return false; // error
return failed_tampered;
}
LOG->Trace( "Done." );
/* The placeholder stats.xml file has an <html> tag. Don't load it, but don't
* warn about it. */
if( xml.name == "html" )
return true; // success
return failed_no_profile;
if( xml.name != "Stats" )
{
WARN_M( xml.name );
return false; // error
return failed_tampered;
}
LOAD_NODE( GeneralData );
@@ -649,7 +646,7 @@ bool Profile::LoadAllFromDir( CString sDir, bool bRequireSignature )
LOAD_NODE( RecentSongScores );
LOAD_NODE( RecentCourseScores );
return true; // success
return success;
}
bool Profile::SaveAllToDir( CString sDir, bool bSignData ) const
@@ -1578,11 +1575,21 @@ XNode* Profile::SaveCoinDataCreateNode() const
void Profile::BackupToDir( CString sFromDir, CString sToDir )
{
FileCopy( sFromDir+EDITABLE_INI, sToDir+EDITABLE_INI );
FileCopy( sFromDir+STATS_XML, sToDir+STATS_XML );
FileCopy( sFromDir+STATS_XML+SIGNATURE_APPEND, sToDir+STATS_XML+SIGNATURE_APPEND );
FileCopy( sFromDir+DONT_SHARE_SIG, sToDir+DONT_SHARE_SIG );
}
bool Profile::CreateNewProfile( CString sProfileDir, CString sName )
{
Profile pro;
pro.m_sDisplayName = sName;
bool bResult = pro.SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData );
FlushDirCache();
return bResult;
}
/*
* (c) 2001-2004 Chris Danford
* All rights reserved.
+3 -1
View File
@@ -260,7 +260,8 @@ public:
//
// Loading and saving
//
bool LoadAllFromDir( CString sDir, bool bRequireSignature ); // return false on a tamper or corruption error
enum LoadResult { success, failed_no_profile, failed_tampered };
LoadResult LoadAllFromDir( CString sDir, bool bRequireSignature );
bool SaveAllToDir( CString sDir, bool bSignData ) const;
void LoadEditableDataFromDir( CString sDir );
@@ -289,6 +290,7 @@ public:
void SaveStatsWebPageToDir( CString sDir ) const;
void SaveMachinePublicKeyToDir( CString sDir ) const;
static bool CreateNewProfile( CString sProfileDir, CString sName );
static void BackupToDir( CString sFromDir, CString sToDir );
private:
+46 -65
View File
@@ -28,7 +28,7 @@ ProfileManager* PROFILEMAN = NULL; // global and accessable from anywhere in our
#define NEW_MEM_CARD_NAME ""
#define USER_PROFILES_DIR "Data/LocalProfiles/"
#define MACHINE_PROFILE_DIR "Data/MachineProfile/"
const CString LAST_GOOD_DIR = "LastGood/";
ProfileManager::ProfileManager()
{
@@ -44,6 +44,7 @@ void ProfileManager::Init()
{
m_bWasLoadedFromMemoryCard[p] = false;
m_bLastLoadWasTamperedOrCorrupt[p] = false;
m_bLastLoadWasFromLastGood[p] = false;
}
LoadMachineProfile();
@@ -77,44 +78,37 @@ bool ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIs
ASSERT( !sProfileDir.empty() );
ASSERT( sProfileDir.Right(1) == "/" );
if( bIsMemCard )
MEMCARDMAN->PauseMountingThread();
m_sProfileDir[pn] = sProfileDir;
m_bWasLoadedFromMemoryCard[pn] = bIsMemCard;
bool bSuccess = m_Profile[pn].LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData );
m_bLastLoadWasFromLastGood[pn] = false;
m_bLastLoadWasTamperedOrCorrupt[pn] = !bSuccess;
// Try to load the original, non-backup data.
Profile::LoadResult lr = m_Profile[pn].LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData );
CString sBackupDir = m_sProfileDir[pn] + LAST_GOOD_DIR;
// Save a backup of the profile now that we've loaded it and know it's good.
// This should be reasonably fast because we're only saving Stats.xml and
// signatures - not all of the files in the Profile.
if( bSuccess )
// Save a backup of the non-backup profile now that we've loaded it and know
// it's good. This should be reasonably fast because we're only saving Stats.xml
// and signatures - not all of the files in the Profile.
if( lr == Profile::success )
{
CString sBackupDir = m_sProfileDir[pn] + "LastGood/";
Profile::BackupToDir( m_sProfileDir[pn], sBackupDir );
}
if( bIsMemCard )
MEMCARDMAN->UnPauseMountingThread();
m_bLastLoadWasTamperedOrCorrupt[pn] = lr == Profile::failed_tampered;
LOG->Trace( "Done loading profile." );
// Try to load from the backup if the original data fails to load
//
if( lr == Profile::failed_tampered )
{
lr = m_Profile[pn].LoadAllFromDir( sBackupDir, PREFSMAN->m_bSignProfileData );
m_bLastLoadWasFromLastGood[pn] = lr == Profile::success;
}
return true;
}
LOG->Trace( "Done loading profile - result %d", lr );
bool ProfileManager::CreateProfile( CString sProfileDir, CString sName )
{
bool bResult;
Profile pro;
pro.m_sDisplayName = sName;
bResult = pro.SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData );
if( !bResult )
return false;
FlushDirCache();
return true;
return lr == Profile::success;
}
bool ProfileManager::LoadLocalProfileFromMachine( PlayerNumber pn )
@@ -138,43 +132,25 @@ bool ProfileManager::LoadProfileFromMemoryCard( PlayerNumber pn )
// mount slot
if( MEMCARDMAN->GetCardState(pn) == MEMORY_CARD_STATE_READY )
{
CString sDir = MEM_CARD_MOUNT_POINT[pn];
// tack on a subdirectory so that we don't write everything to the root
sDir += PREFSMAN->m_sMemoryCardProfileSubdir;
sDir += '/';
bool bResult;
bResult = LoadProfile( pn, sDir, true );
if( bResult )
return true;
CreateMemoryCardProfile( pn );
bResult = LoadProfile( pn, sDir, true );
return bResult;
MEMCARDMAN->PauseMountingThread();
bool bSuccess;
bSuccess = LoadProfile( pn, sDir, true );
MEMCARDMAN->UnPauseMountingThread();
return true; // If a card is inserted, we want to use the memory card to save - even if the Profile load failed.
}
return false;
}
bool ProfileManager::CreateMemoryCardProfile( PlayerNumber pn )
{
// CString sDir = MEM_CARD_DIR[pn];
ASSERT( MEMCARDMAN->GetCardState(pn) == MEMORY_CARD_STATE_READY );
CString sDir = MEM_CARD_MOUNT_POINT[pn];
DEBUG_ASSERT( FILEMAN->IsMounted(sDir) ); // should be called only if we've already mounted
// tack on a subdirectory so that we don't write everything to the root
sDir += PREFSMAN->m_sMemoryCardProfileSubdir;
sDir += '/';
return CreateProfile( sDir, NEW_MEM_CARD_NAME );
}
bool ProfileManager::LoadFirstAvailableProfile( PlayerNumber pn )
{
if( LoadProfileFromMemoryCard(pn) )
@@ -192,7 +168,7 @@ void ProfileManager::SaveAllProfiles() const
FOREACH_HumanPlayer( pn )
{
if( !this->IsUsingProfile(pn) )
if( !IsUsingProfile(pn) )
continue;
this->SaveProfile( pn );
@@ -220,6 +196,7 @@ void ProfileManager::UnloadProfile( PlayerNumber pn )
m_sProfileDir[pn] = "";
m_bWasLoadedFromMemoryCard[pn] = false;
m_bLastLoadWasTamperedOrCorrupt[pn] = false;
m_bLastLoadWasFromLastGood[pn] = false;
m_Profile[pn].InitAll();
}
@@ -261,7 +238,7 @@ bool ProfileManager::CreateLocalProfile( CString sName )
return false;
sProfileDir += "/";
return CreateProfile( sProfileDir, sName );
return Profile::CreateNewProfile( sProfileDir, sName );
}
bool ProfileManager::RenameLocalProfile( CString sProfileID, CString sNewName )
@@ -271,13 +248,14 @@ bool ProfileManager::RenameLocalProfile( CString sProfileID, CString sNewName )
CString sProfileDir = USER_PROFILES_DIR + sProfileID;
Profile pro;
bool bResult;
bResult = pro.LoadAllFromDir( sProfileDir, PREFSMAN->m_bSignProfileData );
if( !bResult )
Profile::LoadResult lr;
lr = pro.LoadAllFromDir( sProfileDir, PREFSMAN->m_bSignProfileData );
if( lr != Profile::success )
return false;
pro.m_sDisplayName = sNewName;
bResult = pro.SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData );
if( !bResult )
bool bSuccess;
bSuccess = pro.SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData );
if( !bSuccess )
return false;
return true;
@@ -314,14 +292,12 @@ void ProfileManager::SaveMachineProfile() const
m_MachineProfile.SaveAllToDir( MACHINE_PROFILE_DIR, false ); /* don't sign machine profiles */
}
void ProfileManager::LoadMachineProfile()
{
if( !m_MachineProfile.LoadAllFromDir(MACHINE_PROFILE_DIR, false) )
Profile::LoadResult lr = m_MachineProfile.LoadAllFromDir(MACHINE_PROFILE_DIR, false);
if( lr == Profile::failed_no_profile )
{
CreateProfile(MACHINE_PROFILE_DIR, "Machine");
Profile::CreateNewProfile(MACHINE_PROFILE_DIR, "Machine");
m_MachineProfile.LoadAllFromDir( MACHINE_PROFILE_DIR, false );
}
@@ -339,6 +315,11 @@ bool ProfileManager::LastLoadWasTamperedOrCorrupt( PlayerNumber pn ) const
return GetProfile(pn) && m_bLastLoadWasTamperedOrCorrupt[pn];
}
bool ProfileManager::LastLoadWasFromLastGood( PlayerNumber pn ) const
{
return GetProfile(pn) && m_bLastLoadWasFromLastGood[pn];
}
CString ProfileManager::GetProfileDir( ProfileSlot slot ) const
{
switch( slot )
+2 -2
View File
@@ -58,6 +58,7 @@ public:
CString GetPlayerName( PlayerNumber pn ) const;
bool ProfileWasLoadedFromMemoryCard( PlayerNumber pn ) const;
bool LastLoadWasTamperedOrCorrupt( PlayerNumber pn ) const;
bool LastLoadWasFromLastGood( PlayerNumber pn ) const;
//
@@ -84,9 +85,7 @@ public:
private:
bool CreateMemoryCardProfile( PlayerNumber pn );
bool LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIsMemCard );
bool CreateProfile( CString sProfileDir, CString sName );
// Directory that contains the profile. Either on local machine or
// on a memory card.
@@ -94,6 +93,7 @@ private:
bool m_bWasLoadedFromMemoryCard[NUM_PLAYERS];
bool m_bLastLoadWasTamperedOrCorrupt[NUM_PLAYERS]; // true if Stats.xml was present, but failed to load (probably because of a signature failure)
bool m_bLastLoadWasFromLastGood[NUM_PLAYERS];
// actual loaded profile data
Profile m_Profile[NUM_PLAYERS];
+11 -2
View File
@@ -53,6 +53,7 @@ ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our p
#define CREDITS_CREDITS THEME->GetMetric ("ScreenSystemLayer","CreditsCredits")
#define CREDITS_NOT_PRESENT THEME->GetMetric ("ScreenSystemLayer","CreditsNotPresent")
#define CREDITS_LOAD_FAILED THEME->GetMetric ("ScreenSystemLayer","CreditsLoadFailed")
#define CREDITS_LOADED_FROM_LAST_GOOD_APPEND THEME->GetMetric ("ScreenSystemLayer","CreditsLoadedFromLastGoodAppend")
#define CREDITS_JOIN_ONLY THEME->GetMetricB("ScreenSystemLayer","CreditsJoinOnly")
const int NUM_SKIPS_TO_SHOW = 5;
@@ -196,7 +197,13 @@ void ScreenSystemLayer::RefreshCreditsMessages()
switch( mcs )
{
case MEMORY_CARD_STATE_NO_CARD:
if( pProfile ) // this is a local machine profile
// this is a local machine profile
if( PROFILEMAN->LastLoadWasFromLastGood(p) && pProfile )
sCredits = pProfile->GetDisplayName() + CREDITS_LOADED_FROM_LAST_GOOD_APPEND;
else if( PROFILEMAN->LastLoadWasTamperedOrCorrupt(p) )
sCredits = CREDITS_LOAD_FAILED;
// Prefer the name of the profile over the name of the card.
else if( pProfile )
sCredits = pProfile->GetDisplayName();
else if( GAMESTATE->PlayersCanJoin() )
sCredits = CREDITS_INSERT_CARD;
@@ -210,7 +217,9 @@ void ScreenSystemLayer::RefreshCreditsMessages()
sCredits = CREDITS_CARD_TOO_LATE;
break;
case MEMORY_CARD_STATE_READY:
if( PROFILEMAN->LastLoadWasTamperedOrCorrupt(p) )
if( PROFILEMAN->LastLoadWasFromLastGood(p) && pProfile )
sCredits = pProfile->GetDisplayName() + CREDITS_LOADED_FROM_LAST_GOOD_APPEND;
else if( PROFILEMAN->LastLoadWasTamperedOrCorrupt(p) )
sCredits = CREDITS_LOAD_FAILED;
// Prefer the name of the profile over the name of the card.
else if( pProfile )