aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/macresman.cpp10
-rw-r--r--common/macresman.h2
-rw-r--r--common/md5.cpp28
-rw-r--r--common/md5.h31
-rw-r--r--engines/advancedDetector.cpp19
-rw-r--r--engines/agi/agi.cpp5
-rw-r--r--engines/agi/sound_2gs.cpp14
-rw-r--r--engines/kyra/staticres.cpp2
-rw-r--r--engines/lastexpress/debug.cpp5
-rw-r--r--engines/scumm/detection.cpp10
-rw-r--r--engines/scumm/file_nes.cpp22
-rw-r--r--engines/tinsel/detection.cpp8
-rw-r--r--test/common/md5.h4
13 files changed, 86 insertions, 74 deletions
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 641702b5ec..d268cfbf89 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -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) {
diff --git a/common/macresman.h b/common/macresman.h
index d47b0ca329..6b67b06bfb 100644
--- a/common/macresman.h
+++ b/common/macresman.h
@@ -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; }
diff --git a/common/md5.cpp b/common/md5.cpp
index df544ca0f0..e4736e85ca 100644
--- a/common/md5.cpp
+++ b/common/md5.cpp
@@ -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
diff --git a/common/md5.h b/common/md5.h
index 1fb937ae9b..29f3aeeb4c 100644
--- a/common/md5.h
+++ b/common/md5.h
@@ -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);
-
-// 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 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);
+
+/**
+ * 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
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index d48fd61118..9be406d714 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -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;
}
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 4dcf5fee5e..cfe921a91e 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -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
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
index cc1cd0f6d5..2748344b36 100644
--- a/engines/agi/sound_2gs.cpp
+++ b/engines/agi/sound_2gs.cpp
@@ -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
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index cf270942bf..fe4bd2ad71 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -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)
diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp
index 50f0109a3f..66949c3d34 100644
--- a/engines/lastexpress/debug.cpp
+++ b/engines/lastexpress/debug.cpp
@@ -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; \
} \
}
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 467282bd43..10224d997d 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -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...
diff --git a/engines/scumm/file_nes.cpp b/engines/scumm/file_nes.cpp
index bfd45d8005..5403354830 100644
--- a/engines/scumm/file_nes.cpp
+++ b/engines/scumm/file_nes.cpp
@@ -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 {
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index cbd0ba267b..22e8806e7e 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -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;
}
diff --git a/test/common/md5.h b/test/common/md5.h
index c59b6dc853..f310845bb9 100644
--- a/test/common/md5.h
+++ b/test/common/md5.h
@@ -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]);