COMMON: Rename and tweak MD5 functions

* names now comply to our naming conventions
* the function computeStreamMD5AsString which computes the MD5
  as a hex string now returns it as a Common::String
* add doxygen comments

svn-id: r54121
This commit is contained in:
Max Horn 2010-11-07 17:16:59 +00:00
parent 036e88d382
commit 4d3a07b494
13 changed files with 85 additions and 73 deletions

View File

@ -88,14 +88,12 @@ uint32 MacResManager::getResForkSize() {
return _resForkSize;
}
bool MacResManager::getResForkMD5(char *md5str, uint32 length) {
Common::String MacResManager::computeResForkMD5AsString(uint32 length) {
if (!hasResFork())
return false;
return Common::String();
ReadStream *stream = new SeekableSubReadStream(_stream, _resForkOffset, _resForkOffset + _resForkSize);
bool retVal = md5_file_string(*stream, md5str, MIN<uint32>(length, _resForkSize));
delete stream;
return retVal;
SeekableSubReadStream resForkStream(_stream, _resForkOffset, _resForkOffset + _resForkSize);
return computeStreamMD5AsString(resForkStream, MIN<uint32>(length, _resForkSize));
}
bool MacResManager::open(Common::String filename) {

View File

@ -82,7 +82,7 @@ public:
Common::SeekableReadStream *getDataFork();
Common::String getResName(uint32 typeID, uint16 resID);
uint32 getResForkSize();
bool getResForkMD5(char *md5str, uint32 length);
Common::String computeResForkMD5AsString(uint32 length = 0);
Common::String getBaseFileName() { return _baseFileName; }

View File

@ -246,7 +246,7 @@ void md5_finish(md5_context *ctx, uint8 digest[16]) {
}
bool md5_file(ReadStream &stream, uint8 digest[16], uint32 length) {
bool computeStreamMD5(ReadStream &stream, uint8 digest[16], uint32 length) {
#ifdef DISABLE_MD5
memset(digest, 0, 16);
@ -267,12 +267,14 @@ bool md5_file(ReadStream &stream, uint8 digest[16], uint32 length) {
while ((i = stream.read(buf, readlen)) > 0) {
md5_update(&ctx, buf, i);
length -= i;
if (restricted && length == 0)
break;
if (restricted) {
length -= i;
if (length == 0)
break;
if (restricted && sizeof(buf) > length)
readlen = length;
if (sizeof(buf) > length)
readlen = length;
}
}
md5_finish(&ctx, digest);
@ -280,16 +282,16 @@ bool md5_file(ReadStream &stream, uint8 digest[16], uint32 length) {
return true;
}
bool md5_file_string(ReadStream &stream, char *md5str, uint32 length) {
String computeStreamMD5AsString(ReadStream &stream, uint32 length) {
String md5;
uint8 digest[16];
if (!md5_file(stream, digest, length))
return false;
for (int i = 0; i < 16; i++) {
snprintf(md5str + i*2, 3, "%02x", (int)digest[i]);
if (computeStreamMD5(stream, digest, length)) {
for (int i = 0; i < 16; i++) {
md5 += String::format("%02x", (int)digest[i]);
}
}
return true;
return md5;
}
} // End of namespace Common

View File

@ -26,18 +26,35 @@
#define COMMON_MD5_H
#include "common/scummsys.h"
#include "common/str.h"
namespace Common {
class ReadStream;
bool md5_file(ReadStream &stream, uint8 digest[16], uint32 length = 0);
/**
* Compute the MD5 checksum of the content of the given ReadStream.
* The 128 bit MD5 checksum is returned directly in the array digest.
* If length is set to a positive value, then only the first length
* bytes of the stream are used to compute the checksum.
* @param[in] stream the stream of whose data the MD5 is computed
* @param[out] digest the computed MD5 checksum
* @param[in] length the number of bytes for which to compute the checksum; 0 means all
* @return true on success, false if an error occurred
*/
bool computeStreamMD5(ReadStream &stream, uint8 digest[16], uint32 length = 0);
// The following method work similar to the above one, but
// instead of computing the binary MD5 digest, it produces
// a human readable lowercase hexstring representing the digest.
// The md5str parameter must point to a buffer of 32+1 chars.
bool md5_file_string(ReadStream &stream, char *md5str, uint32 length = 0);
/**
* Compute the MD5 checksum of the content of the given ReadStream.
* The 128 bit MD5 checksum is converted to a human readable
* lowercase hex string of length 32.
* If length is set to a positive value, then only the first length
* bytes of the stream are used to compute the checksum.
* @param[in] stream the stream of whose data the MD5 is computed
* @param[in] length the number of bytes for which to compute the checksum; 0 means all
* @return the MD5 as a hex string on success, and an empty string if an error occurred
*/
String computeStreamMD5AsString(ReadStream &stream, uint32 length = 0);
} // End of namespace Common

View File

@ -357,7 +357,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
struct SizeMD5 {
int size;
char md5[32+1];
Common::String md5;
};
typedef Common::HashMap<Common::String, SizeMD5, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SizeMD5Map;
@ -374,7 +374,7 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz
printf("of the game you tried to add and its version/language/etc.:\n");
for (SizeMD5Map::const_iterator file = filesSizeMD5.begin(); file != filesSizeMD5.end(); ++file)
printf(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5, file->_value.size);
printf(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5.c_str(), file->_value.size);
printf("\n");
}
@ -459,10 +459,9 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p
Common::MacResManager *macResMan = new Common::MacResManager();
if (macResMan->open(parent, fname)) {
if (!macResMan->getResForkMD5(tmp.md5, params.md5Bytes))
tmp.md5[0] = 0;
tmp.md5 = macResMan->computeResForkMD5AsString(params.md5Bytes);
tmp.size = macResMan->getResForkSize();
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5);
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str());
filesSizeMD5[fname] = tmp;
}
@ -475,14 +474,12 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p
if (testFile.open(allFiles[fname])) {
tmp.size = (int32)testFile.size();
if (!md5_file_string(testFile, tmp.md5, params.md5Bytes))
tmp.md5[0] = 0;
tmp.md5 = Common::computeStreamMD5AsString(testFile, params.md5Bytes);
} else {
tmp.size = -1;
tmp.md5[0] = 0;
}
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5);
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str());
filesSizeMD5[fname] = tmp;
}
}
@ -523,8 +520,8 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p
break;
}
if (fileDesc->md5 != NULL && 0 != strcmp(fileDesc->md5, filesSizeMD5[tstr].md5)) {
debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesSizeMD5[tstr].md5);
if (fileDesc->md5 != NULL && fileDesc->md5 != filesSizeMD5[tstr].md5) {
debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesSizeMD5[tstr].md5.c_str());
fileMissing = true;
break;
}

View File

@ -459,9 +459,8 @@ int AgiEngine::agiLoadResource(int r, int n) {
if (i == errOK && getGameID() == GID_GOLDRUSH && r == rPICTURE && n == 147 && _game.dirPic[n].len == 1982) {
uint8 *pic = _game.pictures[n].rdata;
Common::MemoryReadStream picStream(pic, _game.dirPic[n].len);
char md5str[32+1];
Common::md5_file_string(picStream, md5str, _game.dirPic[n].len);
if (scumm_stricmp(md5str, "1c685eb048656cedcee4eb6eca2cecea") == 0) {
Common::String md5str = Common::computeStreamMD5AsString(picStream, _game.dirPic[n].len);
if (md5str == "1c685eb048656cedcee4eb6eca2cecea") {
pic[0x042] = 0x4B; // 0x49 -> 0x4B
pic[0x043] = 0x66; // 0x26 -> 0x66
pic[0x204] = 0x68; // 0x28 -> 0x68

View File

@ -855,11 +855,10 @@ bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIg
// Check instrument set's md5sum
data->seek(exeInfo.instSetStart);
char md5str[32+1];
Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount);
if (scumm_stricmp(md5str, exeInfo.instSet.md5)) {
Common::String md5str = Common::computeStreamMD5AsString(*data, exeInfo.instSet.byteCount);
if (md5str != exeInfo.instSet.md5) {
warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
md5str, exePath.getPath().c_str());
md5str.c_str(), exePath.getPath().c_str());
}
// Read in the instrument set one instrument at a time
@ -898,12 +897,11 @@ bool SoundGen2GS::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo
// Check that we got the whole wave file
if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) {
// Check wave file's md5sum
char md5str[32+1];
Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE);
if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) {
Common::String md5str = Common::computeStreamMD5AsString(*uint8Wave, SIERRASTANDARD_SIZE);
if (md5str != exeInfo.instSet.waveFileMd5) {
warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \
"Please report the information on the previous line to the ScummVM team.\n" \
"Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix);
"Using the wave file as it is - music may sound weird", md5str.c_str(), exeInfo.exePrefix);
}
uint8Wave->seek(0); // Seek wave to its start

View File

@ -57,7 +57,7 @@ bool checkKyraDat(Common::SeekableReadStream *file) {
uint8 digestCalc[16];
file->seek(0, SEEK_SET);
if (!Common::md5_file(*file, digestCalc, size))
if (!Common::computeStreamMD5(*file, digestCalc, size))
return false;
for (int i = 0; i < 16; ++i)

View File

@ -281,9 +281,8 @@ bool Debugger::cmdDumpFiles(int argc, const char **) {
restoreArchive(); \
return true; \
} \
char md5str[32+1]; \
Common::md5_file_string(*stream, md5str, (uint32)stream->size()); \
debugC(1, kLastExpressDebugResource, "%s, %d, %s", (*it)->getName().c_str(), stream->size(), (char *)&md5str); \
Common::String md5str = Common::computeStreamMD5AsString(*stream); \
debugC(1, kLastExpressDebugResource, "%s, %d, %s", (*it)->getName().c_str(), stream->size(), md5str.c_str()); \
delete stream; \
} \
}

View File

@ -422,7 +422,6 @@ static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map
static void detectGames(const Common::FSList &fslist, Common::List<DetectorResult> &results, const char *gameid) {
DescMap fileMD5Map;
DetectorResult dr;
char md5str[32+1];
// Dive one level down since mac indy3/loom has its files split into directories. See Bug #1438631
composeFileHashMap(fslist, fileMD5Map, 2, directoryGlobs);
@ -479,10 +478,13 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul
tmp->open(d.node);
}
if (tmp && tmp->isOpen() && Common::md5_file_string(*tmp, md5str, kMD5FileSizeLimit)) {
Common::String md5str;
if (tmp && tmp->isOpen())
md5str = computeStreamMD5AsString(*tmp, kMD5FileSizeLimit);
if (!md5str.empty()) {
d.md5 = md5str;
d.md5Entry = findInMD5Table(md5str);
d.md5Entry = findInMD5Table(md5str.c_str());
dr.md5 = d.md5;
@ -494,7 +496,7 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul
int filesize = tmp->size();
if (d.md5Entry->filesize != filesize)
debug(1, "SCUMM detector found matching file '%s' with MD5 %s, size %d\n",
file.c_str(), md5str, filesize);
file.c_str(), md5str.c_str(), filesize);
// Sanity check: We *should* have found a matching gameid / variant at this point.
// If not, then there's a bug in our data tables...

View File

@ -1369,34 +1369,36 @@ bool ScummNESFile::generateIndex() {
bool ScummNESFile::open(const Common::String &filename) {
if (_ROMset == kROMsetNum) {
char md5str[32+1];
Common::String md5str;
File f;
f.open(filename);
if (f.isOpen() && Common::md5_file_string(f, md5str)) {
if (f.isOpen())
md5str = Common::computeStreamMD5AsString(f);
if (!md5str.empty()) {
if (!strcmp(md5str, "3905799e081b80a61d4460b7b733c206")) {
if (md5str == "3905799e081b80a61d4460b7b733c206") {
_ROMset = kROMsetUSA;
debug(1, "ROM contents verified as Maniac Mansion (USA)");
} else if (!strcmp(md5str, "d8d07efcb88f396bee0b402b10c3b1c9")) {
} else if (md5str == "d8d07efcb88f396bee0b402b10c3b1c9") {
_ROMset = kROMsetEurope;
debug(1, "ROM contents verified as Maniac Mansion (Europe)");
} else if (!strcmp(md5str, "22d07d6c386c9c25aca5dac2a0c0d94b")) {
} else if (md5str == "22d07d6c386c9c25aca5dac2a0c0d94b") {
_ROMset = kROMsetSweden;
debug(1, "ROM contents verified as Maniac Mansion (Sweden)");
} else if (!strcmp(md5str, "81bbfa181184cb494e7a81dcfa94fbd9")) {
} else if (md5str == "81bbfa181184cb494e7a81dcfa94fbd9") {
_ROMset = kROMsetFrance;
debug(2, "ROM contents verified as Maniac Mansion (France)");
} else if (!strcmp(md5str, "257f8c14d8c584f7ddd601bcb00920c7")) {
} else if (md5str == "257f8c14d8c584f7ddd601bcb00920c7") {
_ROMset = kROMsetGermany;
debug(2, "ROM contents verified as Maniac Mansion (Germany)");
} else if (!strcmp(md5str, "f163cf53f7850e43fb482471e5c52e1a")) {
} else if (md5str == "f163cf53f7850e43fb482471e5c52e1a") {
_ROMset = kROMsetSpain;
debug(2, "ROM contents verified as Maniac Mansion (Spain)");
} else if (!strcmp(md5str, "54a68a5f5e3c86da42b7ca5f51e79b1d")) {
} else if (md5str == "54a68a5f5e3c86da42b7ca5f51e79b1d") {
_ROMset = kROMsetItaly;
debug(2, "ROM contents verified as Maniac Mansion (Italy)");
} else {
error("Unsupported Maniac Mansion ROM, md5: %s", md5str);
error("Unsupported Maniac Mansion ROM, md5: %s", md5str.c_str());
return false;
}
} else {

View File

@ -191,7 +191,7 @@ bool TinselMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
struct SizeMD5 {
int size;
char md5[32+1];
Common::String md5;
};
typedef Common::HashMap<Common::String, SizeMD5, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SizeMD5Map;
typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
@ -268,11 +268,9 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &
if (testFile.open(allFiles[fname])) {
tmp.size = (int32)testFile.size();
if (!md5_file_string(testFile, tmp.md5, detectionParams.md5Bytes))
tmp.md5[0] = 0;
tmp.md5 = computeStreamMD5AsString(testFile, detectionParams.md5Bytes);
} else {
tmp.size = -1;
tmp.md5[0] = 0;
}
filesSizeMD5[fname] = tmp;
@ -318,7 +316,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &
break;
}
if (fileDesc->md5 != NULL && 0 != strcmp(fileDesc->md5, filesSizeMD5[tstr].md5)) {
if (fileDesc->md5 != NULL && fileDesc->md5 != filesSizeMD5[tstr].md5) {
fileMissing = true;
break;
}

View File

@ -29,14 +29,14 @@ static const char *md5_test_digest[] = {
class MD5TestSuite : public CxxTest::TestSuite {
public:
void test_md5_file() {
void test_computeStreamMD5() {
int i, j;
char output[33];
unsigned char md5sum[16];
for (i = 0; i < 7; i++) {
Common::MemoryReadStream stream((const byte *)md5_test_string[i], strlen(md5_test_string[i]));
Common::md5_file(stream, md5sum);
Common::computeStreamMD5(stream, md5sum);
for (j = 0; j < 16; j++) {
sprintf(output + j * 2, "%02x", md5sum[j]);