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.

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