Merge pull request #4676 from jmarshallnz/dont_set_scraper_on_tvshow_on_nfo
[vuplus_xbmc] / xbmc / utils / md5.cpp
1 /*
2  *      Copyright (C) 2009-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "md5.h"
22 #include "utils/StringUtils.h"
23
24 typedef unsigned char md5byte;
25
26 static void MD5Init(struct MD5Context *context);
27 static void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
28 static void MD5Final(unsigned char digest[16], struct MD5Context *context);
29 static void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
30
31
32 XBMC::XBMC_MD5::XBMC_MD5(void)
33 {
34   MD5Init(&m_ctx);
35 }
36
37 XBMC::XBMC_MD5::~XBMC_MD5(void)
38 {}
39
40 void XBMC::XBMC_MD5::append(const void *inBuf, size_t inLen)
41 {
42   MD5Update(&m_ctx, (md5byte*)inBuf, inLen);
43 }
44
45 void XBMC::XBMC_MD5::append(const CStdString& str)
46 {
47   append((unsigned char*) str.c_str(), (unsigned int) str.length());
48 }
49
50 void XBMC::XBMC_MD5::getDigest(unsigned char digest[16])
51 {
52   MD5Final(digest, &m_ctx);
53 }
54
55 void XBMC::XBMC_MD5::getDigest(CStdString& digest)
56 {
57   unsigned char szBuf[16] = {'\0'};
58   getDigest(szBuf);
59   digest = StringUtils::Format("%02X%02X%02X%02X%02X%02X%02X%02X"\
60                                "%02X%02X%02X%02X%02X%02X%02X%02X",
61                                szBuf[0], szBuf[1], szBuf[2],
62                                szBuf[3], szBuf[4], szBuf[5], szBuf[6], szBuf[7], szBuf[8],
63                                szBuf[9], szBuf[10], szBuf[11], szBuf[12], szBuf[13], szBuf[14],
64                                szBuf[15]);
65 }
66
67 CStdString XBMC::XBMC_MD5::GetMD5(const CStdString &text)
68 {
69   if (text.empty())
70     return "";
71   XBMC_MD5 state;
72   CStdString digest;
73   state.append(text);
74   state.getDigest(digest);
75   return digest;
76 }
77
78 /*
79  * This code implements the MD5 message-digest algorithm.
80  * The algorithm is due to Ron Rivest.  This code was
81  * written by Colin Plumb in 1993, no copyright is claimed.
82  * This code is in the public domain; do with it what you wish.
83  *
84  * Equivalent code is available from RSA Data Security, Inc.
85  * This code has been tested against that, and is equivalent,
86  * except that you don't need to include two pages of legalese
87  * with every copy.
88  *
89  * To compute the message digest of a chunk of bytes, declare an
90  * MD5Context structure, pass it to MD5Init, call MD5Update as
91  * needed on buffers full of bytes, and then call MD5Final, which
92  * will fill a supplied 16-byte array with the digest.
93  *
94  * Changed so as no longer to depend on Colin Plumb's `usual.h' header
95  * definitions; now uses stuff from dpkg's config.h.
96  *  - Ian Jackson <ian@chiark.greenend.org.uk>.
97  * Still in the public domain.
98  */
99
100 #include "md5.h"
101
102 #include <sys/types.h>          /* for stupid systems */
103 #include <string.h>             /* for memcpy() */
104 #if defined(HAVE_CONFIG_H) && !defined(TARGET_WINDOWS)
105 #include "../config.h"
106 #endif
107
108 #ifdef WORDS_BIGENDIAN
109 void
110 byteSwap(uint32_t *buf, unsigned words)
111 {
112         md5byte *p = (md5byte *)buf;
113
114         do {
115                 *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
116                         ((unsigned)p[1] << 8 | p[0]);
117                 p += 4;
118         } while (--words);
119 }
120 #else
121 #define byteSwap(buf,words)
122 #endif
123
124 /*
125  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
126  * initialization constants.
127  */
128 static void
129 MD5Init(struct MD5Context *ctx)
130 {
131         ctx->buf[0] = 0x67452301;
132         ctx->buf[1] = 0xefcdab89;
133         ctx->buf[2] = 0x98badcfe;
134         ctx->buf[3] = 0x10325476;
135
136         ctx->bytes[0] = 0;
137         ctx->bytes[1] = 0;
138 }
139
140 /*
141  * Update context to reflect the concatenation of another buffer full
142  * of bytes.
143  */
144 static void
145 MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
146 {
147         uint32_t t;
148
149         /* Update byte count */
150
151         t = ctx->bytes[0];
152         if ((ctx->bytes[0] = t + len) < t)
153                 ctx->bytes[1]++;        /* Carry from low to high */
154
155         t = 64 - (t & 0x3f);    /* Space available in ctx->in (at least 1) */
156         if (t > len) {
157                 memcpy((md5byte *)ctx->in + 64 - t, buf, len);
158                 return;
159         }
160         /* First chunk is an odd size */
161         memcpy((md5byte *)ctx->in + 64 - t, buf, t);
162         byteSwap(ctx->in, 16);
163         MD5Transform(ctx->buf, ctx->in);
164         buf += t;
165         len -= t;
166
167         /* Process data in 64-byte chunks */
168         while (len >= 64) {
169                 memcpy(ctx->in, buf, 64);
170                 byteSwap(ctx->in, 16);
171                 MD5Transform(ctx->buf, ctx->in);
172                 buf += 64;
173                 len -= 64;
174         }
175
176         /* Handle any remaining bytes of data. */
177         memcpy(ctx->in, buf, len);
178 }
179
180 /*
181  * Final wrapup - pad to 64-byte boundary with the bit pattern
182  * 1 0* (64-bit count of bits processed, MSB-first)
183  */
184 static void
185 MD5Final(md5byte digest[16], struct MD5Context *ctx)
186 {
187         int count = ctx->bytes[0] & 0x3f;       /* Number of bytes in ctx->in */
188         md5byte *p = (md5byte *)ctx->in + count;
189
190         /* Set the first char of padding to 0x80.  There is always room. */
191         *p++ = 0x80;
192
193         /* Bytes of padding needed to make 56 bytes (-8..55) */
194         count = 56 - 1 - count;
195
196         if (count < 0) {        /* Padding forces an extra block */
197                 memset(p, 0, count + 8);
198                 byteSwap(ctx->in, 16);
199                 MD5Transform(ctx->buf, ctx->in);
200                 p = (md5byte *)ctx->in;
201                 count = 56;
202         }
203         memset(p, 0, count);
204         byteSwap(ctx->in, 14);
205
206         /* Append length in bits and transform */
207         ctx->in[14] = ctx->bytes[0] << 3;
208         ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
209         MD5Transform(ctx->buf, ctx->in);
210
211         byteSwap(ctx->buf, 4);
212         memcpy(digest, ctx->buf, 16);
213         memset(ctx, 0, sizeof(*ctx));   /* In case it's sensitive */
214 }
215
216 #ifndef ASM_MD5
217
218 /* The four core functions - F1 is optimized somewhat */
219
220 /* #define F1(x, y, z) (x & y | ~x & z) */
221 #define F1(x, y, z) (z ^ (x & (y ^ z)))
222 #define F2(x, y, z) F1(z, x, y)
223 #define F3(x, y, z) (x ^ y ^ z)
224 #define F4(x, y, z) (y ^ (x | ~z))
225
226 /* This is the central step in the MD5 algorithm. */
227 #define MD5STEP(f,w,x,y,z,in,s) \
228          (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
229
230 /*
231  * The core of the MD5 algorithm, this alters an existing MD5 hash to
232  * reflect the addition of 16 longwords of new data.  MD5Update blocks
233  * the data and converts bytes into longwords for this routine.
234  */
235 static void
236 MD5Transform(uint32_t buf[4], uint32_t const in[16])
237 {
238         register uint32_t a, b, c, d;
239
240         a = buf[0];
241         b = buf[1];
242         c = buf[2];
243         d = buf[3];
244
245         MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
246         MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
247         MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
248         MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
249         MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
250         MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
251         MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
252         MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
253         MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
254         MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
255         MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
256         MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
257         MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
258         MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
259         MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
260         MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
261
262         MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
263         MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
264         MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
265         MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
266         MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
267         MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
268         MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
269         MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
270         MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
271         MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
272         MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
273         MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
274         MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
275         MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
276         MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
277         MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
278
279         MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
280         MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
281         MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
282         MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
283         MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
284         MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
285         MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
286         MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
287         MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
288         MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
289         MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
290         MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
291         MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
292         MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
293         MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
294         MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
295
296         MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
297         MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
298         MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
299         MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
300         MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
301         MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
302         MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
303         MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
304         MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
305         MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
306         MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
307         MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
308         MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
309         MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
310         MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
311         MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
312
313         buf[0] += a;
314         buf[1] += b;
315         buf[2] += c;
316         buf[3] += d;
317 }
318
319 #endif