fixed high scores hashing

This commit is contained in:
thrust26 2021-01-04 10:45:47 +01:00
parent e90cb925b0
commit 44a8ef1db3
3 changed files with 43 additions and 24 deletions

View File

@ -564,6 +564,24 @@ Int32 HighScoresManager::fromBCD(uInt8 bcd) const
return (bcd >> 4) * 10 + bcd % 16;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string HighScoresManager::hash(ScoresData& data) const
{
ostringstream buf;
buf << HIGHSCORE_HEADER << data.md5 << md5Props() << data.variation;
for(uInt32 r = 0; r < NUM_RANKS && data.scores[r].score; ++r)
{
buf << data.scores[r].score
<< data.scores[r].special
<< data.scores[r].name
<< data.scores[r].date;
}
return MD5::hash(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void HighScoresManager::saveHighScores(ScoresData& data) const
{
@ -571,14 +589,13 @@ void HighScoresManager::saveHighScores(ScoresData& data) const
{
json hsObject = json::object();
json hsData = json::object();
json jScores = json::array();
// Add header so that if the high score format changes in the future,
// we'll know right away, without having to parse the rest of the data
hsData[VERSION] = HIGHSCORE_HEADER;
hsData[MD5] = data.md5;
hsData[VARIATION] = data.variation;
json jScores = json::array();
hsObject[VERSION] = HIGHSCORE_HEADER;
hsObject[MD5] = data.md5;
hsObject[PROPCHECK] = md5Props();
for(uInt32 r = 0; r < NUM_RANKS && data.scores[r].score; ++r)
{
@ -592,10 +609,10 @@ void HighScoresManager::saveHighScores(ScoresData& data) const
jScores.push_back(jScore);
}
hsData[SCORES] = jScores;
hsData[PROPCHECK] = md5Props();
hsData[VARIATION] = data.variation;
hsObject[DATA] = hsData;
hsObject[CHECKSUM] = MD5::hash(hsData.dump());
hsObject[CHECKSUM] = hash(data);
myHighscoreRepository->save(data.md5, to_string(data.variation), hsObject.dump(2));
}
@ -608,11 +625,11 @@ void HighScoresManager::saveHighScores(ScoresData& data) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void HighScoresManager::loadHighScores(ScoresData& data)
{
bool invalid = false;
ostringstream buf;
clearHighScores(data);
bool invalid = false;
try {
Variant serializedHighscore;
@ -620,27 +637,27 @@ void HighScoresManager::loadHighScores(ScoresData& data)
{
const json hsObject = json::parse(serializedHighscore.toString());
if(hsObject.contains(DATA))
// First test if we have a valid header
// If so, do a complete high score data load
if(!hsObject.contains(VERSION) || hsObject.at(VERSION) != HIGHSCORE_HEADER)
buf << "Error: Incompatible high scores data for variation " << data.variation << ".";
else if(hsObject.contains(DATA))
{
const json hsData = hsObject.at(DATA);
// First test if we have a valid header
// If so, do a complete high score data load
if(!hsData.contains(VERSION) || hsData.at(VERSION) != HIGHSCORE_HEADER)
buf << "Error: Incompatible high scores data for variation " << data.variation << ".";
else
{
if(!load(hsData, data)
|| !hsData.contains(PROPCHECK) || hsData.at(PROPCHECK) != md5Props()
|| !hsObject.contains(CHECKSUM) || hsObject.at(CHECKSUM) != MD5::hash(hsData.dump()))
|| !hsObject.contains(MD5) || hsObject.at(MD5) != data.md5
|| !hsObject.contains(PROPCHECK) || hsObject.at(PROPCHECK) != md5Props()
|| !hsObject.contains(CHECKSUM) || hsObject.at(CHECKSUM) != hash(data))
invalid = true;
else
return;
}
return; // scores loaded OK
}
else
invalid = true;
}
else
return; // no scores for variation found
}
catch(...) { invalid = true; }
@ -655,8 +672,7 @@ void HighScoresManager::loadHighScores(ScoresData& data)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool HighScoresManager::load(const json& hsData, ScoresData& data)
{
if(!hsData.contains(MD5) || hsData.at(MD5) != data.md5
|| !hsData.contains(VARIATION) || hsData.at(VARIATION) != data.variation
if(!hsData.contains(VARIATION) || hsData.at(VARIATION) != data.variation
|| !hsData.contains(SCORES))
return false;

View File

@ -18,7 +18,7 @@
#ifndef HIGHSCORES_MANAGER_HXX
#define HIGHSCORES_MANAGER_HXX
#define HIGHSCORE_HEADER "06010000highscores"
#define HIGHSCORE_HEADER "06050000highscores"
class OSystem;
@ -232,6 +232,7 @@ class HighScoresManager
uInt16 fromHexStr(const string& addr) const;
Int32 fromBCD(uInt8 bcd) const;
string hash(HSM::ScoresData& data) const;
/**
Loads the current high scores for this game and variation from the given JSON object.

View File

@ -204,6 +204,8 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent,
addDefaultsOKCancelBGroup(wid, _font, "Save", "Cancel", " Reset ");
_defaultWidget->setToolTip("Click to reset all high scores of this variation.");
addToFocusList(wid);
_focusedWidget = _okWidget; // start with focus on 'Save' button
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -