ROOT logo
// @(#)root/base:$Id: TMD5.cxx 27658 2009-02-28 05:34:57Z pcanal $
// Author: Fons Rademakers   29/9/2001

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TMD5                                                                 //
//                                                                      //
// This code implements the MD5 message-digest algorithm.               //
// The algorithm is due to Ron Rivest. This code was                    //
// written by Colin Plumb in 1993, no copyright is claimed.             //
// This code is in the public domain; do with it what you wish.         //
//                                                                      //
// Equivalent code is available from RSA Data Security, Inc.            //
// This code has been tested against that, and is equivalent,           //
// except that you don't need to include two pages of legalese          //
// with every copy.                                                     //
//                                                                      //
// To compute the message digest of a chunk of bytes, create an         //
// TMD5 object, call Update() as needed on buffers full of bytes, and   //
// then call Final(), which will, optionally, fill a supplied 16-byte   //
// array with the  digest.                                              //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TMD5.h"
#include "TError.h"
#include "TSystem.h"
#include "Bytes.h"
#include <string.h>
#include <errno.h>
#ifdef R__WIN32
#include <io.h>
#endif

ClassImp(TMD5)

//______________________________________________________________________________
TMD5::TMD5()
{
   // Create TMD5 object. Set bit count to 0 and buffer to mysterious
   // initialization constants.

   fBuf[0] = 0x67452301;
   fBuf[1] = 0xefcdab89;
   fBuf[2] = 0x98badcfe;
   fBuf[3] = 0x10325476;

   fBits[0] = 0;
   fBits[1] = 0;

   memset(fIn, 0, 64);

   memset(fDigest, 0, 16);
   fFinalized = kFALSE;
}

//______________________________________________________________________________
TMD5::TMD5(const UChar_t *digest)
{
   // Create finalized TMD5 object containing passed in 16 byte digest.

   if (digest)
      memcpy(fDigest, digest, 16);
   else {
      memset(fDigest, 0, 16);
      Error("TMD5::TMD5", "digest is 0");
   }
   fFinalized = kTRUE;
}

//______________________________________________________________________________
TMD5::TMD5(const TMD5 &md5)
{
   // MD5 copy ctor. Special copy ctor avoids copying unnecessary
   // temp arrays when finalized.

   if (!md5.fFinalized) {
      memcpy(fBuf,  md5.fBuf,  4*sizeof(UInt_t));
      memcpy(fBits, md5.fBits, 2*sizeof(UInt_t));
      memcpy(fIn,   md5.fIn,   64);
   }

   memcpy(fDigest, md5.fDigest, 16);
   fFinalized = md5.fFinalized;
}

//______________________________________________________________________________
TMD5 &TMD5::operator=(const TMD5 &rhs)
{
   // MD5 assignment operator. Special assignment operator avoids
   // copying unnecessary temp arrays when finalized.

   if (this != &rhs) {
      if (!rhs.fFinalized) {
         memcpy(fBuf,  rhs.fBuf,  4*sizeof(UInt_t));
         memcpy(fBits, rhs.fBits, 2*sizeof(UInt_t));
         memcpy(fIn,   rhs.fIn,   64);
      }
      memcpy(fDigest, rhs.fDigest, 16);
      fFinalized = rhs.fFinalized;
   }
   return *this;
}

//______________________________________________________________________________
void TMD5::Update(const UChar_t *buf, UInt_t len)
{
   // Update TMD5 object to reflect the concatenation of another buffer full
   // of bytes.

   if (fFinalized) {
      Error("TMD5::Update", "Final() has already been called");
      return;
   }

   UInt_t t;

   // Update bitcount
   t = fBits[0];
   if ((fBits[0] = t + (len << 3)) < t)
      fBits[1]++;        // Carry from low to high
   fBits[1] += len >> 29;

   t = (t >> 3) & 0x3f;

   // Handle any leading odd-sized chunks
   if (t) {
      UChar_t *p = (UChar_t *) fIn + t;

      t = 64 - t;
      if (len < t) {
         memcpy(p, buf, len);
         return;
      }
      memcpy(p, buf, t);
      Transform(fBuf, fIn);
      buf += t;
      len -= t;
   }

   // Process data in 64-byte chunks
   while (len >= 64) {
      memcpy(fIn, buf, 64);
      Transform(fBuf, fIn);
      buf += 64;
      len -= 64;
   }

   // Handle any remaining bytes of data
   memcpy(fIn, buf, len);
}

//______________________________________________________________________________
void TMD5::Final(UChar_t digest[16])
{
   // MD5 finalization, ends an MD5 message-digest operation, writing the
   // the message digest and zeroizing the context.
   // Returns digest.

   Final();
   memcpy(digest, fDigest, 16);
}

//______________________________________________________________________________
void TMD5::Final()
{
   // MD5 finalization, ends an MD5 message-digest operation, writing the
   // the message digest and zeroizing the context.

   if (fFinalized)
      return;

   UInt_t  count, padLen;
   UChar_t bits[8];

   static UChar_t padding[64] = {
      0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   };

   // Save number of bits
   Encode(bits, fBits, 8);

   // Pad out to 56 mod 64
   count = (fBits[0] >> 3) & 0x3f;
   padLen = (count < 56) ? (56 - count) : (120 - count);
   Update(padding, padLen);

   // Append length (before padding)
   Update(bits, 8);

   // Store state in digest
   Encode(fDigest, fBuf, 16);

   // Zero out sensitive information
   memset(fBuf,  0, 4*sizeof(UInt_t));
   memset(fBits, 0, 2*sizeof(UInt_t));
   memset(fIn,   0, 64);

   fFinalized = kTRUE;
}

//______________________________________________________________________________
void TMD5::Print() const
{
   // Print digest in ascii hex form.

   if (!fFinalized) {
      Error("TMD5::Print", "Final() has not yet been called");
      return;
   }

   for (int i = 0; i < 16; i++)
      printf("%.2hx", (UShort_t)fDigest[i]);
   printf("\n");
}

//______________________________________________________________________________
const char *TMD5::AsString() const
{
   // Return message digest as string. Returns "" in case Final() has
   // not yet been called. Copy result because it points to a statically
   // allocated string.

   if (!fFinalized) {
      Error("TMD5::AsString", "Final() has not yet been called");
      return "";
   }

   static char s[33];

   for (int i = 0; i < 16; i++)
      sprintf((s+2*i), "%.2hx", (UShort_t)fDigest[i]);
   s[32] = 0;

   return s;
}

//______________________________________________________________________________
void TMD5::Encode(UChar_t *out, const UInt_t *in, UInt_t len)
{
   // Encodes input into output. Assumes len is a multiple of 4.

   UInt_t i, j;

   for (i = 0, j = 0; j < len; i++, j += 4) {
      out[j]   = (UChar_t)(in[i] & 0xff);
      out[j+1] = (UChar_t)((in[i] >> 8) & 0xff);
      out[j+2] = (UChar_t)((in[i] >> 16) & 0xff);
      out[j+3] = (UChar_t)((in[i] >> 24) & 0xff);
   }
}

//______________________________________________________________________________
void TMD5::Decode(UInt_t *out, const UChar_t *in, UInt_t len)
{
   // Decodes input into output. Assumes len is a multiple of 4.

   UInt_t i, j;

   for (i = 0, j = 0; j < len; i++, j += 4)
      out[i] = ((UInt_t)in[j])           | (((UInt_t)in[j+1]) << 8) |
               (((UInt_t)in[j+2]) << 16) | (((UInt_t)in[j+3]) << 24);
}


// The four core functions - F1 is optimized somewhat
//#define F1(x, y, z) (x & y | ~x & z)
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))

// This is the central step in the MD5 algorithm
#define MD5STEP(f, w, x, y, z, data, s) \
        ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )

//______________________________________________________________________________
void TMD5::Transform(UInt_t buf[4], const UChar_t in[64])
{
   // The core of the MD5 algorithm, this alters an existing MD5 hash to
   // reflect the addition of 16 longwords of new data. Update() blocks
   // the data and converts bytes into longwords for this routine.

   UInt_t a, b, c, d, x[16];

   a = buf[0];
   b = buf[1];
   c = buf[2];
   d = buf[3];

   Decode(x, in, 64);

   MD5STEP(F1, a, b, c, d, x[0]  + 0xd76aa478, 7);
   MD5STEP(F1, d, a, b, c, x[1]  + 0xe8c7b756, 12);
   MD5STEP(F1, c, d, a, b, x[2]  + 0x242070db, 17);
   MD5STEP(F1, b, c, d, a, x[3]  + 0xc1bdceee, 22);
   MD5STEP(F1, a, b, c, d, x[4]  + 0xf57c0faf, 7);
   MD5STEP(F1, d, a, b, c, x[5]  + 0x4787c62a, 12);
   MD5STEP(F1, c, d, a, b, x[6]  + 0xa8304613, 17);
   MD5STEP(F1, b, c, d, a, x[7]  + 0xfd469501, 22);
   MD5STEP(F1, a, b, c, d, x[8]  + 0x698098d8, 7);
   MD5STEP(F1, d, a, b, c, x[9]  + 0x8b44f7af, 12);
   MD5STEP(F1, c, d, a, b, x[10] + 0xffff5bb1, 17);
   MD5STEP(F1, b, c, d, a, x[11] + 0x895cd7be, 22);
   MD5STEP(F1, a, b, c, d, x[12] + 0x6b901122, 7);
   MD5STEP(F1, d, a, b, c, x[13] + 0xfd987193, 12);
   MD5STEP(F1, c, d, a, b, x[14] + 0xa679438e, 17);
   MD5STEP(F1, b, c, d, a, x[15] + 0x49b40821, 22);

   MD5STEP(F2, a, b, c, d, x[1]  + 0xf61e2562, 5);
   MD5STEP(F2, d, a, b, c, x[6]  + 0xc040b340, 9);
   MD5STEP(F2, c, d, a, b, x[11] + 0x265e5a51, 14);
   MD5STEP(F2, b, c, d, a, x[0]  + 0xe9b6c7aa, 20);
   MD5STEP(F2, a, b, c, d, x[5]  + 0xd62f105d, 5);
   MD5STEP(F2, d, a, b, c, x[10] + 0x02441453, 9);
   MD5STEP(F2, c, d, a, b, x[15] + 0xd8a1e681, 14);
   MD5STEP(F2, b, c, d, a, x[4]  + 0xe7d3fbc8, 20);
   MD5STEP(F2, a, b, c, d, x[9]  + 0x21e1cde6, 5);
   MD5STEP(F2, d, a, b, c, x[14] + 0xc33707d6, 9);
   MD5STEP(F2, c, d, a, b, x[3]  + 0xf4d50d87, 14);
   MD5STEP(F2, b, c, d, a, x[8]  + 0x455a14ed, 20);
   MD5STEP(F2, a, b, c, d, x[13] + 0xa9e3e905, 5);
   MD5STEP(F2, d, a, b, c, x[2]  + 0xfcefa3f8, 9);
   MD5STEP(F2, c, d, a, b, x[7]  + 0x676f02d9, 14);
   MD5STEP(F2, b, c, d, a, x[12] + 0x8d2a4c8a, 20);

   MD5STEP(F3, a, b, c, d, x[5]  + 0xfffa3942, 4);
   MD5STEP(F3, d, a, b, c, x[8]  + 0x8771f681, 11);
   MD5STEP(F3, c, d, a, b, x[11] + 0x6d9d6122, 16);
   MD5STEP(F3, b, c, d, a, x[14] + 0xfde5380c, 23);
   MD5STEP(F3, a, b, c, d, x[1]  + 0xa4beea44, 4);
   MD5STEP(F3, d, a, b, c, x[4]  + 0x4bdecfa9, 11);
   MD5STEP(F3, c, d, a, b, x[7]  + 0xf6bb4b60, 16);
   MD5STEP(F3, b, c, d, a, x[10] + 0xbebfbc70, 23);
   MD5STEP(F3, a, b, c, d, x[13] + 0x289b7ec6, 4);
   MD5STEP(F3, d, a, b, c, x[0]  + 0xeaa127fa, 11);
   MD5STEP(F3, c, d, a, b, x[3]  + 0xd4ef3085, 16);
   MD5STEP(F3, b, c, d, a, x[6]  + 0x04881d05, 23);
   MD5STEP(F3, a, b, c, d, x[9]  + 0xd9d4d039, 4);
   MD5STEP(F3, d, a, b, c, x[12] + 0xe6db99e5, 11);
   MD5STEP(F3, c, d, a, b, x[15] + 0x1fa27cf8, 16);
   MD5STEP(F3, b, c, d, a, x[2]  + 0xc4ac5665, 23);

   MD5STEP(F4, a, b, c, d, x[0]  + 0xf4292244, 6);
   MD5STEP(F4, d, a, b, c, x[7]  + 0x432aff97, 10);
   MD5STEP(F4, c, d, a, b, x[14] + 0xab9423a7, 15);
   MD5STEP(F4, b, c, d, a, x[5]  + 0xfc93a039, 21);
   MD5STEP(F4, a, b, c, d, x[12] + 0x655b59c3, 6);
   MD5STEP(F4, d, a, b, c, x[3]  + 0x8f0ccc92, 10);
   MD5STEP(F4, c, d, a, b, x[10] + 0xffeff47d, 15);
   MD5STEP(F4, b, c, d, a, x[1]  + 0x85845dd1, 21);
   MD5STEP(F4, a, b, c, d, x[8]  + 0x6fa87e4f, 6);
   MD5STEP(F4, d, a, b, c, x[15] + 0xfe2ce6e0, 10);
   MD5STEP(F4, c, d, a, b, x[6]  + 0xa3014314, 15);
   MD5STEP(F4, b, c, d, a, x[13] + 0x4e0811a1, 21);
   MD5STEP(F4, a, b, c, d, x[4]  + 0xf7537e82, 6);
   MD5STEP(F4, d, a, b, c, x[11] + 0xbd3af235, 10);
   MD5STEP(F4, c, d, a, b, x[2]  + 0x2ad7d2bb, 15);
   MD5STEP(F4, b, c, d, a, x[9]  + 0xeb86d391, 21);

   buf[0] += a;
   buf[1] += b;
   buf[2] += c;
   buf[3] += d;

   // Zero out sensitive information
   memset(x, 0, sizeof(x));
}

//______________________________________________________________________________
Bool_t operator==(const TMD5 &m1, const TMD5 &m2)
{
   // Compare two message digests for equality.

   // Make sure both are finalized.
   if (!m1.fFinalized || !m2.fFinalized) {
      if (!m1.fFinalized)
         Error("TMD5::operator==(const TMD5&, const TMD5&)", "arg1.Final() not yet called");
      if (!m2.fFinalized)
         Error("TMD5::operator==(const TMD5&, const TMD5&)", "arg2.Final() not yet called");
      return kFALSE;
   }

   for (int i = 0; i < 16; i++)
      if (m1.fDigest[i] != m2.fDigest[i])
         return kFALSE;

   return kTRUE;
}

//______________________________________________________________________________
TMD5 *TMD5::ReadChecksum(const char *file)
{
   // Returns checksum stored in ASCII in specified file. Use to read files
   // created via WriteChecksum(). The returned TMD5 object must be deleted
   // by the user. Returns 0 in case the file cannot be opened or in case of
   // error. Static utlity function.

   FILE *fid = fopen(file, "r");
   if (!fid) {
      // file cannot be opened
      return 0;
   }

   char buf[33];

   fgets(buf, 33, fid);

   UChar_t digest[16];
   for (int i = 0; i < 16; i++) {
      UShort_t d;
      char s = buf[2+2*i];
      buf[2+2*i] = 0;
      sscanf(buf+2*i, "%hx", &d);
      buf[2+2*i] = s;
      digest[i] = (UChar_t) d;
   }

   fclose(fid);

   TMD5 *md5 = new TMD5(digest);
   return md5;
}

//______________________________________________________________________________
Int_t TMD5::WriteChecksum(const char *file, const TMD5 *md5)
{
   // Writes checksum in ASCII format to specified file. This file can
   // directly be read by ReadChecksum(). The md5 must have been finalized.
   // Returns -1 in case file cannot be opened or in case of error,
   // 0 otherwise. Static utility function.

   FILE *fid = fopen(file, "w");
   if (!fid) {
      // file cannot be opened
      return -1;
   }

   fputs(md5->AsString(), fid);

   fclose(fid);

   return 0;
}

//______________________________________________________________________________
TMD5 *TMD5::FileChecksum(const char *file)
{
   // Returns checksum of specified file. The returned TMD5 object must
   // be deleted by the user. Returns 0 in case the file does not exists
   // or in case of error. This function preserves the modtime of the file
   // so it can be safely used in conjunction with methods that keep track
   // of the file's modtime. Static utility function.

   Long64_t size;
   Long_t id, flags, modtime;
   if (gSystem->GetPathInfo(file, &id, &size, &flags, &modtime) == 0) {
      if (flags > 1) {
         Error("TMD5::FileChecksum", "%s not a regular file (%ld)", file, flags);
         return 0;
      }
   } else {
      // file does not exist
      return 0;
   }

#ifndef WIN32
   Int_t fd = open(file, O_RDONLY);
#else
   Int_t fd = open(file, O_RDONLY | O_BINARY);
#endif
   if (fd < 0) {
      Error("TMD5::FileChecksum", "cannot open %s in read mode", file);
      return 0;
   }

   TMD5 *md5 = new TMD5;

   Long64_t pos = 0;
   const Int_t bufSize = 8192;
   UChar_t buf[bufSize];

   while (pos < size) {
      Long64_t left = Long64_t(size - pos);
      if (left > bufSize)
         left = bufSize;
      Int_t siz;
      while ((siz = read(fd, buf, left)) < 0 && TSystem::GetErrno() == EINTR)
         TSystem::ResetErrno();
      if (siz < 0 || siz != left) {
         Error("TMD5::FileChecksum", "error reading from file %s", file);
         close(fd);
         delete md5;
         return 0;
      }

      md5->Update(buf, left);

      pos += left;
   }

   close(fd);

   md5->Final();

   gSystem->Utime(file, modtime, modtime);

   return md5;
}

//______________________________________________________________________________
Int_t TMD5::FileChecksum(const char *file, UChar_t digest[16])
{
   // Returns checksum of specified file in digest argument. Returns -1 in
   // case of error, 0 otherwise. This method preserves the modtime of the
   // file so it can be safely used in conjunction with methods that keep
   // track of the file's modtime. Static utility function.

   TMD5 *md5 = FileChecksum(file);
   if (md5) {
      memcpy(digest, md5->fDigest, 16);
      delete md5;
      return 0;
   } else
      memset(digest, 0, 16);

   return -1;
}

//______________________________________________________________________________
TBuffer &operator<<(TBuffer &buf, const TMD5 &uuid) 
{
   // Input operator.  Delegate to Streamer.

   R__ASSERT( buf.IsWriting() );

   const_cast<TMD5&>(uuid).Streamer(buf); 
   return buf; 
}

 TMD5.cxx:1
 TMD5.cxx:2
 TMD5.cxx:3
 TMD5.cxx:4
 TMD5.cxx:5
 TMD5.cxx:6
 TMD5.cxx:7
 TMD5.cxx:8
 TMD5.cxx:9
 TMD5.cxx:10
 TMD5.cxx:11
 TMD5.cxx:12
 TMD5.cxx:13
 TMD5.cxx:14
 TMD5.cxx:15
 TMD5.cxx:16
 TMD5.cxx:17
 TMD5.cxx:18
 TMD5.cxx:19
 TMD5.cxx:20
 TMD5.cxx:21
 TMD5.cxx:22
 TMD5.cxx:23
 TMD5.cxx:24
 TMD5.cxx:25
 TMD5.cxx:26
 TMD5.cxx:27
 TMD5.cxx:28
 TMD5.cxx:29
 TMD5.cxx:30
 TMD5.cxx:31
 TMD5.cxx:32
 TMD5.cxx:33
 TMD5.cxx:34
 TMD5.cxx:35
 TMD5.cxx:36
 TMD5.cxx:37
 TMD5.cxx:38
 TMD5.cxx:39
 TMD5.cxx:40
 TMD5.cxx:41
 TMD5.cxx:42
 TMD5.cxx:43
 TMD5.cxx:44
 TMD5.cxx:45
 TMD5.cxx:46
 TMD5.cxx:47
 TMD5.cxx:48
 TMD5.cxx:49
 TMD5.cxx:50
 TMD5.cxx:51
 TMD5.cxx:52
 TMD5.cxx:53
 TMD5.cxx:54
 TMD5.cxx:55
 TMD5.cxx:56
 TMD5.cxx:57
 TMD5.cxx:58
 TMD5.cxx:59
 TMD5.cxx:60
 TMD5.cxx:61
 TMD5.cxx:62
 TMD5.cxx:63
 TMD5.cxx:64
 TMD5.cxx:65
 TMD5.cxx:66
 TMD5.cxx:67
 TMD5.cxx:68
 TMD5.cxx:69
 TMD5.cxx:70
 TMD5.cxx:71
 TMD5.cxx:72
 TMD5.cxx:73
 TMD5.cxx:74
 TMD5.cxx:75
 TMD5.cxx:76
 TMD5.cxx:77
 TMD5.cxx:78
 TMD5.cxx:79
 TMD5.cxx:80
 TMD5.cxx:81
 TMD5.cxx:82
 TMD5.cxx:83
 TMD5.cxx:84
 TMD5.cxx:85
 TMD5.cxx:86
 TMD5.cxx:87
 TMD5.cxx:88
 TMD5.cxx:89
 TMD5.cxx:90
 TMD5.cxx:91
 TMD5.cxx:92
 TMD5.cxx:93
 TMD5.cxx:94
 TMD5.cxx:95
 TMD5.cxx:96
 TMD5.cxx:97
 TMD5.cxx:98
 TMD5.cxx:99
 TMD5.cxx:100
 TMD5.cxx:101
 TMD5.cxx:102
 TMD5.cxx:103
 TMD5.cxx:104
 TMD5.cxx:105
 TMD5.cxx:106
 TMD5.cxx:107
 TMD5.cxx:108
 TMD5.cxx:109
 TMD5.cxx:110
 TMD5.cxx:111
 TMD5.cxx:112
 TMD5.cxx:113
 TMD5.cxx:114
 TMD5.cxx:115
 TMD5.cxx:116
 TMD5.cxx:117
 TMD5.cxx:118
 TMD5.cxx:119
 TMD5.cxx:120
 TMD5.cxx:121
 TMD5.cxx:122
 TMD5.cxx:123
 TMD5.cxx:124
 TMD5.cxx:125
 TMD5.cxx:126
 TMD5.cxx:127
 TMD5.cxx:128
 TMD5.cxx:129
 TMD5.cxx:130
 TMD5.cxx:131
 TMD5.cxx:132
 TMD5.cxx:133
 TMD5.cxx:134
 TMD5.cxx:135
 TMD5.cxx:136
 TMD5.cxx:137
 TMD5.cxx:138
 TMD5.cxx:139
 TMD5.cxx:140
 TMD5.cxx:141
 TMD5.cxx:142
 TMD5.cxx:143
 TMD5.cxx:144
 TMD5.cxx:145
 TMD5.cxx:146
 TMD5.cxx:147
 TMD5.cxx:148
 TMD5.cxx:149
 TMD5.cxx:150
 TMD5.cxx:151
 TMD5.cxx:152
 TMD5.cxx:153
 TMD5.cxx:154
 TMD5.cxx:155
 TMD5.cxx:156
 TMD5.cxx:157
 TMD5.cxx:158
 TMD5.cxx:159
 TMD5.cxx:160
 TMD5.cxx:161
 TMD5.cxx:162
 TMD5.cxx:163
 TMD5.cxx:164
 TMD5.cxx:165
 TMD5.cxx:166
 TMD5.cxx:167
 TMD5.cxx:168
 TMD5.cxx:169
 TMD5.cxx:170
 TMD5.cxx:171
 TMD5.cxx:172
 TMD5.cxx:173
 TMD5.cxx:174
 TMD5.cxx:175
 TMD5.cxx:176
 TMD5.cxx:177
 TMD5.cxx:178
 TMD5.cxx:179
 TMD5.cxx:180
 TMD5.cxx:181
 TMD5.cxx:182
 TMD5.cxx:183
 TMD5.cxx:184
 TMD5.cxx:185
 TMD5.cxx:186
 TMD5.cxx:187
 TMD5.cxx:188
 TMD5.cxx:189
 TMD5.cxx:190
 TMD5.cxx:191
 TMD5.cxx:192
 TMD5.cxx:193
 TMD5.cxx:194
 TMD5.cxx:195
 TMD5.cxx:196
 TMD5.cxx:197
 TMD5.cxx:198
 TMD5.cxx:199
 TMD5.cxx:200
 TMD5.cxx:201
 TMD5.cxx:202
 TMD5.cxx:203
 TMD5.cxx:204
 TMD5.cxx:205
 TMD5.cxx:206
 TMD5.cxx:207
 TMD5.cxx:208
 TMD5.cxx:209
 TMD5.cxx:210
 TMD5.cxx:211
 TMD5.cxx:212
 TMD5.cxx:213
 TMD5.cxx:214
 TMD5.cxx:215
 TMD5.cxx:216
 TMD5.cxx:217
 TMD5.cxx:218
 TMD5.cxx:219
 TMD5.cxx:220
 TMD5.cxx:221
 TMD5.cxx:222
 TMD5.cxx:223
 TMD5.cxx:224
 TMD5.cxx:225
 TMD5.cxx:226
 TMD5.cxx:227
 TMD5.cxx:228
 TMD5.cxx:229
 TMD5.cxx:230
 TMD5.cxx:231
 TMD5.cxx:232
 TMD5.cxx:233
 TMD5.cxx:234
 TMD5.cxx:235
 TMD5.cxx:236
 TMD5.cxx:237
 TMD5.cxx:238
 TMD5.cxx:239
 TMD5.cxx:240
 TMD5.cxx:241
 TMD5.cxx:242
 TMD5.cxx:243
 TMD5.cxx:244
 TMD5.cxx:245
 TMD5.cxx:246
 TMD5.cxx:247
 TMD5.cxx:248
 TMD5.cxx:249
 TMD5.cxx:250
 TMD5.cxx:251
 TMD5.cxx:252
 TMD5.cxx:253
 TMD5.cxx:254
 TMD5.cxx:255
 TMD5.cxx:256
 TMD5.cxx:257
 TMD5.cxx:258
 TMD5.cxx:259
 TMD5.cxx:260
 TMD5.cxx:261
 TMD5.cxx:262
 TMD5.cxx:263
 TMD5.cxx:264
 TMD5.cxx:265
 TMD5.cxx:266
 TMD5.cxx:267
 TMD5.cxx:268
 TMD5.cxx:269
 TMD5.cxx:270
 TMD5.cxx:271
 TMD5.cxx:272
 TMD5.cxx:273
 TMD5.cxx:274
 TMD5.cxx:275
 TMD5.cxx:276
 TMD5.cxx:277
 TMD5.cxx:278
 TMD5.cxx:279
 TMD5.cxx:280
 TMD5.cxx:281
 TMD5.cxx:282
 TMD5.cxx:283
 TMD5.cxx:284
 TMD5.cxx:285
 TMD5.cxx:286
 TMD5.cxx:287
 TMD5.cxx:288
 TMD5.cxx:289
 TMD5.cxx:290
 TMD5.cxx:291
 TMD5.cxx:292
 TMD5.cxx:293
 TMD5.cxx:294
 TMD5.cxx:295
 TMD5.cxx:296
 TMD5.cxx:297
 TMD5.cxx:298
 TMD5.cxx:299
 TMD5.cxx:300
 TMD5.cxx:301
 TMD5.cxx:302
 TMD5.cxx:303
 TMD5.cxx:304
 TMD5.cxx:305
 TMD5.cxx:306
 TMD5.cxx:307
 TMD5.cxx:308
 TMD5.cxx:309
 TMD5.cxx:310
 TMD5.cxx:311
 TMD5.cxx:312
 TMD5.cxx:313
 TMD5.cxx:314
 TMD5.cxx:315
 TMD5.cxx:316
 TMD5.cxx:317
 TMD5.cxx:318
 TMD5.cxx:319
 TMD5.cxx:320
 TMD5.cxx:321
 TMD5.cxx:322
 TMD5.cxx:323
 TMD5.cxx:324
 TMD5.cxx:325
 TMD5.cxx:326
 TMD5.cxx:327
 TMD5.cxx:328
 TMD5.cxx:329
 TMD5.cxx:330
 TMD5.cxx:331
 TMD5.cxx:332
 TMD5.cxx:333
 TMD5.cxx:334
 TMD5.cxx:335
 TMD5.cxx:336
 TMD5.cxx:337
 TMD5.cxx:338
 TMD5.cxx:339
 TMD5.cxx:340
 TMD5.cxx:341
 TMD5.cxx:342
 TMD5.cxx:343
 TMD5.cxx:344
 TMD5.cxx:345
 TMD5.cxx:346
 TMD5.cxx:347
 TMD5.cxx:348
 TMD5.cxx:349
 TMD5.cxx:350
 TMD5.cxx:351
 TMD5.cxx:352
 TMD5.cxx:353
 TMD5.cxx:354
 TMD5.cxx:355
 TMD5.cxx:356
 TMD5.cxx:357
 TMD5.cxx:358
 TMD5.cxx:359
 TMD5.cxx:360
 TMD5.cxx:361
 TMD5.cxx:362
 TMD5.cxx:363
 TMD5.cxx:364
 TMD5.cxx:365
 TMD5.cxx:366
 TMD5.cxx:367
 TMD5.cxx:368
 TMD5.cxx:369
 TMD5.cxx:370
 TMD5.cxx:371
 TMD5.cxx:372
 TMD5.cxx:373
 TMD5.cxx:374
 TMD5.cxx:375
 TMD5.cxx:376
 TMD5.cxx:377
 TMD5.cxx:378
 TMD5.cxx:379
 TMD5.cxx:380
 TMD5.cxx:381
 TMD5.cxx:382
 TMD5.cxx:383
 TMD5.cxx:384
 TMD5.cxx:385
 TMD5.cxx:386
 TMD5.cxx:387
 TMD5.cxx:388
 TMD5.cxx:389
 TMD5.cxx:390
 TMD5.cxx:391
 TMD5.cxx:392
 TMD5.cxx:393
 TMD5.cxx:394
 TMD5.cxx:395
 TMD5.cxx:396
 TMD5.cxx:397
 TMD5.cxx:398
 TMD5.cxx:399
 TMD5.cxx:400
 TMD5.cxx:401
 TMD5.cxx:402
 TMD5.cxx:403
 TMD5.cxx:404
 TMD5.cxx:405
 TMD5.cxx:406
 TMD5.cxx:407
 TMD5.cxx:408
 TMD5.cxx:409
 TMD5.cxx:410
 TMD5.cxx:411
 TMD5.cxx:412
 TMD5.cxx:413
 TMD5.cxx:414
 TMD5.cxx:415
 TMD5.cxx:416
 TMD5.cxx:417
 TMD5.cxx:418
 TMD5.cxx:419
 TMD5.cxx:420
 TMD5.cxx:421
 TMD5.cxx:422
 TMD5.cxx:423
 TMD5.cxx:424
 TMD5.cxx:425
 TMD5.cxx:426
 TMD5.cxx:427
 TMD5.cxx:428
 TMD5.cxx:429
 TMD5.cxx:430
 TMD5.cxx:431
 TMD5.cxx:432
 TMD5.cxx:433
 TMD5.cxx:434
 TMD5.cxx:435
 TMD5.cxx:436
 TMD5.cxx:437
 TMD5.cxx:438
 TMD5.cxx:439
 TMD5.cxx:440
 TMD5.cxx:441
 TMD5.cxx:442
 TMD5.cxx:443
 TMD5.cxx:444
 TMD5.cxx:445
 TMD5.cxx:446
 TMD5.cxx:447
 TMD5.cxx:448
 TMD5.cxx:449
 TMD5.cxx:450
 TMD5.cxx:451
 TMD5.cxx:452
 TMD5.cxx:453
 TMD5.cxx:454
 TMD5.cxx:455
 TMD5.cxx:456
 TMD5.cxx:457
 TMD5.cxx:458
 TMD5.cxx:459
 TMD5.cxx:460
 TMD5.cxx:461
 TMD5.cxx:462
 TMD5.cxx:463
 TMD5.cxx:464
 TMD5.cxx:465
 TMD5.cxx:466
 TMD5.cxx:467
 TMD5.cxx:468
 TMD5.cxx:469
 TMD5.cxx:470
 TMD5.cxx:471
 TMD5.cxx:472
 TMD5.cxx:473
 TMD5.cxx:474
 TMD5.cxx:475
 TMD5.cxx:476
 TMD5.cxx:477
 TMD5.cxx:478
 TMD5.cxx:479
 TMD5.cxx:480
 TMD5.cxx:481
 TMD5.cxx:482
 TMD5.cxx:483
 TMD5.cxx:484
 TMD5.cxx:485
 TMD5.cxx:486
 TMD5.cxx:487
 TMD5.cxx:488
 TMD5.cxx:489
 TMD5.cxx:490
 TMD5.cxx:491
 TMD5.cxx:492
 TMD5.cxx:493
 TMD5.cxx:494
 TMD5.cxx:495
 TMD5.cxx:496
 TMD5.cxx:497
 TMD5.cxx:498
 TMD5.cxx:499
 TMD5.cxx:500
 TMD5.cxx:501
 TMD5.cxx:502
 TMD5.cxx:503
 TMD5.cxx:504
 TMD5.cxx:505
 TMD5.cxx:506
 TMD5.cxx:507
 TMD5.cxx:508
 TMD5.cxx:509
 TMD5.cxx:510
 TMD5.cxx:511
 TMD5.cxx:512
 TMD5.cxx:513
 TMD5.cxx:514
 TMD5.cxx:515
 TMD5.cxx:516
 TMD5.cxx:517
 TMD5.cxx:518
 TMD5.cxx:519
 TMD5.cxx:520
 TMD5.cxx:521
 TMD5.cxx:522
 TMD5.cxx:523
 TMD5.cxx:524
 TMD5.cxx:525
 TMD5.cxx:526
 TMD5.cxx:527
 TMD5.cxx:528
 TMD5.cxx:529
 TMD5.cxx:530
 TMD5.cxx:531
 TMD5.cxx:532
 TMD5.cxx:533
 TMD5.cxx:534
 TMD5.cxx:535
 TMD5.cxx:536
 TMD5.cxx:537
 TMD5.cxx:538
 TMD5.cxx:539
 TMD5.cxx:540
 TMD5.cxx:541
 TMD5.cxx:542
 TMD5.cxx:543
 TMD5.cxx:544
 TMD5.cxx:545
 TMD5.cxx:546
 TMD5.cxx:547
 TMD5.cxx:548
 TMD5.cxx:549
 TMD5.cxx:550