The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. class MD5Generator
  19. {
  20. public:
  21. MD5Generator() noexcept
  22. {
  23. state[0] = 0x67452301;
  24. state[1] = 0xefcdab89;
  25. state[2] = 0x98badcfe;
  26. state[3] = 0x10325476;
  27. count[0] = 0;
  28. count[1] = 0;
  29. }
  30. void processBlock (const void* data, size_t dataSize) noexcept
  31. {
  32. int bufferPos = ((count[0] >> 3) & 0x3F);
  33. count[0] += (uint32) (dataSize << 3);
  34. if (count[0] < ((uint32) dataSize << 3))
  35. count[1]++;
  36. count[1] += (uint32) (dataSize >> 29);
  37. const size_t spaceLeft = 64 - (size_t) bufferPos;
  38. size_t i = 0;
  39. if (dataSize >= spaceLeft)
  40. {
  41. memcpy (buffer + bufferPos, data, spaceLeft);
  42. transform (buffer);
  43. for (i = spaceLeft; i + 64 <= dataSize; i += 64)
  44. transform (static_cast <const char*> (data) + i);
  45. bufferPos = 0;
  46. }
  47. memcpy (buffer + bufferPos, static_cast <const char*> (data) + i, dataSize - i);
  48. }
  49. void transform (const void* bufferToTransform) noexcept
  50. {
  51. uint32 a = state[0];
  52. uint32 b = state[1];
  53. uint32 c = state[2];
  54. uint32 d = state[3];
  55. uint32 x[16];
  56. encode (x, bufferToTransform, 64);
  57. enum Constants
  58. {
  59. S11 = 7, S12 = 12, S13 = 17, S14 = 22, S21 = 5, S22 = 9, S23 = 14, S24 = 20,
  60. S31 = 4, S32 = 11, S33 = 16, S34 = 23, S41 = 6, S42 = 10, S43 = 15, S44 = 21
  61. };
  62. FF (a, b, c, d, x[ 0], S11, 0xd76aa478); FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
  63. FF (c, d, a, b, x[ 2], S13, 0x242070db); FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
  64. FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
  65. FF (c, d, a, b, x[ 6], S13, 0xa8304613); FF (b, c, d, a, x[ 7], S14, 0xfd469501);
  66. FF (a, b, c, d, x[ 8], S11, 0x698098d8); FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
  67. FF (c, d, a, b, x[10], S13, 0xffff5bb1); FF (b, c, d, a, x[11], S14, 0x895cd7be);
  68. FF (a, b, c, d, x[12], S11, 0x6b901122); FF (d, a, b, c, x[13], S12, 0xfd987193);
  69. FF (c, d, a, b, x[14], S13, 0xa679438e); FF (b, c, d, a, x[15], S14, 0x49b40821);
  70. GG (a, b, c, d, x[ 1], S21, 0xf61e2562); GG (d, a, b, c, x[ 6], S22, 0xc040b340);
  71. GG (c, d, a, b, x[11], S23, 0x265e5a51); GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
  72. GG (a, b, c, d, x[ 5], S21, 0xd62f105d); GG (d, a, b, c, x[10], S22, 0x02441453);
  73. GG (c, d, a, b, x[15], S23, 0xd8a1e681); GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
  74. GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); GG (d, a, b, c, x[14], S22, 0xc33707d6);
  75. GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
  76. GG (a, b, c, d, x[13], S21, 0xa9e3e905); GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
  77. GG (c, d, a, b, x[ 7], S23, 0x676f02d9); GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
  78. HH (a, b, c, d, x[ 5], S31, 0xfffa3942); HH (d, a, b, c, x[ 8], S32, 0x8771f681);
  79. HH (c, d, a, b, x[11], S33, 0x6d9d6122); HH (b, c, d, a, x[14], S34, 0xfde5380c);
  80. HH (a, b, c, d, x[ 1], S31, 0xa4beea44); HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
  81. HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); HH (b, c, d, a, x[10], S34, 0xbebfbc70);
  82. HH (a, b, c, d, x[13], S31, 0x289b7ec6); HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
  83. HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); HH (b, c, d, a, x[ 6], S34, 0x04881d05);
  84. HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); HH (d, a, b, c, x[12], S32, 0xe6db99e5);
  85. HH (c, d, a, b, x[15], S33, 0x1fa27cf8); HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
  86. II (a, b, c, d, x[ 0], S41, 0xf4292244); II (d, a, b, c, x[ 7], S42, 0x432aff97);
  87. II (c, d, a, b, x[14], S43, 0xab9423a7); II (b, c, d, a, x[ 5], S44, 0xfc93a039);
  88. II (a, b, c, d, x[12], S41, 0x655b59c3); II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
  89. II (c, d, a, b, x[10], S43, 0xffeff47d); II (b, c, d, a, x[ 1], S44, 0x85845dd1);
  90. II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
  91. II (c, d, a, b, x[ 6], S43, 0xa3014314); II (b, c, d, a, x[13], S44, 0x4e0811a1);
  92. II (a, b, c, d, x[ 4], S41, 0xf7537e82); II (d, a, b, c, x[11], S42, 0xbd3af235);
  93. II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); II (b, c, d, a, x[ 9], S44, 0xeb86d391);
  94. state[0] += a;
  95. state[1] += b;
  96. state[2] += c;
  97. state[3] += d;
  98. zerostruct (x);
  99. }
  100. void finish (void* result) noexcept
  101. {
  102. unsigned char encodedLength[8];
  103. encode (encodedLength, count, 8);
  104. // Pad out to 56 mod 64.
  105. const int index = (count[0] >> 3) & 0x3f;
  106. const int paddingLength = (index < 56) ? (56 - index)
  107. : (120 - index);
  108. uint8 paddingBuffer[64] = { 0x80 }; // first byte is 0x80, remaining bytes are zero.
  109. processBlock (paddingBuffer, (size_t) paddingLength);
  110. processBlock (encodedLength, 8);
  111. encode (result, state, 16);
  112. zerostruct (buffer);
  113. }
  114. private:
  115. uint8 buffer [64];
  116. uint32 state [4];
  117. uint32 count [2];
  118. static void encode (void* const output, const void* const input, const int numBytes) noexcept
  119. {
  120. for (int i = 0; i < (numBytes >> 2); ++i)
  121. static_cast<uint32*> (output)[i] = ByteOrder::swapIfBigEndian (static_cast<const uint32*> (input) [i]);
  122. }
  123. static inline uint32 rotateLeft (const uint32 x, const uint32 n) noexcept { return (x << n) | (x >> (32 - n)); }
  124. static inline uint32 F (const uint32 x, const uint32 y, const uint32 z) noexcept { return (x & y) | (~x & z); }
  125. static inline uint32 G (const uint32 x, const uint32 y, const uint32 z) noexcept { return (x & z) | (y & ~z); }
  126. static inline uint32 H (const uint32 x, const uint32 y, const uint32 z) noexcept { return x ^ y ^ z; }
  127. static inline uint32 I (const uint32 x, const uint32 y, const uint32 z) noexcept { return y ^ (x | ~z); }
  128. static void FF (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) noexcept
  129. {
  130. a += F (b, c, d) + x + ac;
  131. a = rotateLeft (a, s) + b;
  132. }
  133. static void GG (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) noexcept
  134. {
  135. a += G (b, c, d) + x + ac;
  136. a = rotateLeft (a, s) + b;
  137. }
  138. static void HH (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) noexcept
  139. {
  140. a += H (b, c, d) + x + ac;
  141. a = rotateLeft (a, s) + b;
  142. }
  143. static void II (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) noexcept
  144. {
  145. a += I (b, c, d) + x + ac;
  146. a = rotateLeft (a, s) + b;
  147. }
  148. };
  149. //==============================================================================
  150. MD5::MD5() noexcept
  151. {
  152. zerostruct (result);
  153. }
  154. MD5::MD5 (const MD5& other) noexcept
  155. {
  156. memcpy (result, other.result, sizeof (result));
  157. }
  158. MD5& MD5::operator= (const MD5& other) noexcept
  159. {
  160. memcpy (result, other.result, sizeof (result));
  161. return *this;
  162. }
  163. //==============================================================================
  164. MD5::MD5 (const MemoryBlock& data) noexcept
  165. {
  166. processData (data.getData(), data.getSize());
  167. }
  168. MD5::MD5 (const void* data, const size_t numBytes) noexcept
  169. {
  170. processData (data, numBytes);
  171. }
  172. MD5::MD5 (CharPointer_UTF8 utf8) noexcept
  173. {
  174. jassert (utf8.getAddress() != nullptr);
  175. processData (utf8.getAddress(), utf8.sizeInBytes() - 1);
  176. }
  177. MD5 MD5::fromUTF32 (const String& text)
  178. {
  179. MD5Generator generator;
  180. String::CharPointerType t (text.getCharPointer());
  181. while (! t.isEmpty())
  182. {
  183. uint32 unicodeChar = ByteOrder::swapIfBigEndian ((uint32) t.getAndAdvance());
  184. generator.processBlock (&unicodeChar, sizeof (unicodeChar));
  185. }
  186. MD5 m;
  187. generator.finish (m.result);
  188. return m;
  189. }
  190. MD5::MD5 (InputStream& input, int64 numBytesToRead)
  191. {
  192. processStream (input, numBytesToRead);
  193. }
  194. MD5::MD5 (const File& file)
  195. {
  196. FileInputStream fin (file);
  197. if (fin.getStatus().wasOk())
  198. processStream (fin, -1);
  199. else
  200. zerostruct (result);
  201. }
  202. MD5::~MD5() noexcept {}
  203. void MD5::processData (const void* data, size_t numBytes) noexcept
  204. {
  205. MD5Generator generator;
  206. generator.processBlock (data, numBytes);
  207. generator.finish (result);
  208. }
  209. void MD5::processStream (InputStream& input, int64 numBytesToRead)
  210. {
  211. MD5Generator generator;
  212. if (numBytesToRead < 0)
  213. numBytesToRead = std::numeric_limits<int64>::max();
  214. while (numBytesToRead > 0)
  215. {
  216. uint8 tempBuffer [512];
  217. const int bytesRead = input.read (tempBuffer, (int) jmin (numBytesToRead, (int64) sizeof (tempBuffer)));
  218. if (bytesRead <= 0)
  219. break;
  220. numBytesToRead -= bytesRead;
  221. generator.processBlock (tempBuffer, (size_t) bytesRead);
  222. }
  223. generator.finish (result);
  224. }
  225. //==============================================================================
  226. MemoryBlock MD5::getRawChecksumData() const
  227. {
  228. return MemoryBlock (result, sizeof (result));
  229. }
  230. String MD5::toHexString() const
  231. {
  232. return String::toHexString (result, sizeof (result), 0);
  233. }
  234. //==============================================================================
  235. bool MD5::operator== (const MD5& other) const noexcept { return memcmp (result, other.result, sizeof (result)) == 0; }
  236. bool MD5::operator!= (const MD5& other) const noexcept { return ! operator== (other); }