Switch to side-by-side view

--- a/src/utils/md5.cpp
+++ b/src/utils/md5.cpp
@@ -27,7 +27,7 @@
  * This code is the same as the code published by RSA Inc.  It has been
  * edited for clarity and style only.
  */
-
+#ifndef TEST_MD5
 #include <string.h>
 
 #include "md5.h"
@@ -316,3 +316,129 @@
 	/* Zeroize sensitive information. */
 	memset ((void *)x, 0, sizeof (x));
 }
+
+/*************** Convenience  / utilities */
+void MD5Final(string &digest, MD5_CTX *context)
+{
+    unsigned char d[16];
+    MD5Final (d, context);
+    digest.assign((const char *)d, 16);
+}
+
+string& MD5String(const string& data, string& digest)
+{
+    MD5_CTX ctx;
+    MD5Init(&ctx);
+    MD5Update(&ctx, (const unsigned char*)data.c_str(), data.length());
+    MD5Final(digest, &ctx);
+    return digest;
+}
+
+string& MD5HexPrint(const string& digest, string &out)
+{
+    out.erase();
+    out.reserve(33);
+    static const char hex[]="0123456789abcdef";
+    const unsigned char *hash = (const unsigned char *)digest.c_str();
+    for (int i = 0; i < 16; i++) {
+	out.append(1, hex[hash[i] >> 4]);
+	out.append(1, hex[hash[i] & 0x0f]);
+    }
+    return out;
+}
+string& MD5HexScan(const string& xdigest, string& digest)
+{
+    digest.erase();
+    if (xdigest.length() != 32) {
+	return digest;
+    }
+    for (unsigned int i = 0; i < 16; i++) {
+	unsigned int val;
+	if (sscanf(xdigest.c_str() + 2*i, "%2x", &val) != 1) {
+	    digest.erase();
+	    return digest;
+	}
+	digest.append(1, (unsigned char)val);
+    }
+    return digest;
+}
+
+#include "readfile.h"
+class FileScanMd5 : public FileScanDo {
+public:
+    FileScanMd5(string& d) : digest(d) {}
+    virtual bool init(unsigned int size, string *reason) 
+    {
+	MD5Init(&ctx);
+	return true;
+    }
+    virtual bool data(const char *buf, int cnt, string* reason) 
+    {
+	MD5Update(&ctx, (const unsigned char*)buf, cnt);
+	return true;
+    }
+    string &digest;
+    MD5_CTX ctx;
+};
+bool MD5File(const string& filename, string &digest, string *reason)
+{
+    FileScanMd5 md5er(digest);
+    if (!file_scan(filename, &md5er, reason))
+	return false;
+    // We happen to know that digest and md5er.digest are the same object
+    MD5Final(md5er.digest, &md5er.ctx);
+    return true;
+}
+#else
+
+// Test driver
+#include <stdlib.h>
+
+#include <string>
+#include <iostream>
+#include "md5.h"
+
+using namespace std;
+
+static const char *thisprog;
+static char usage [] =
+"trmd5 filename\n\n"
+;
+static void
+Usage(void)
+{
+    fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
+    exit(1);
+}
+
+int main(int argc, const char **argv)
+{
+    thisprog = argv[0];
+    argc--; argv++;
+
+  if (argc != 1)
+    Usage();
+  string filename =  *argv++;argc--;
+
+  string reason, digest;
+  if (!MD5File(filename, digest, &reason)) {
+      cerr << reason << endl;
+      exit(1);
+  } else {
+      string hex;
+      cout <<  "MD5 (" << filename << ") = " << MD5HexPrint(digest, hex) << endl;
+
+      string digest1;
+      MD5HexScan(hex, digest1);
+      if (digest1.compare(digest)) {
+	  cout << "MD5HexScan Failure" << endl;
+	  cout <<  MD5HexPrint(digest, hex) << " " << digest.length() << " -> " 
+	       << MD5HexPrint(digest1, hex) << " " << digest1.length() << endl;
+	  exit(1);
+      }
+
+  }
+  exit(0);
+}
+
+#endif