XMMS2
bindata.c
Go to the documentation of this file.
1/* XMMS2 - X Music Multiplexer System
2 * Copyright (C) 2003-2011 XMMS2 Team
3 *
4 * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 */
16
17#include <glib.h>
18#include <string.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <sys/time.h>
23#include <errno.h>
24
27#include "xmmsc/xmmsc_ipc_msg.h"
28
29#include "xmms/xmms_log.h"
30
31#include "xmms/xmms_bindata.h"
32
34#include "xmmspriv/xmms_ipc.h"
38#include "xmmspriv/xmms_utils.h"
39
40struct xmms_bindata_St {
41 xmms_object_t obj;
42 const gchar *bindir;
43};
44
45static xmms_bindata_t *global_bindata;
46
47static void xmms_bindata_destroy (xmms_object_t *obj);
48
49typedef unsigned char md5_byte_t; /* 8-bit byte */
50typedef unsigned int md5_word_t; /* 32-bit word */
51
52/* Define the state of the MD5 Algorithm. */
53typedef struct md5_state_s {
54 md5_word_t count[2]; /* message length in bits, lsw first */
55 md5_word_t abcd[4]; /* digest buffer */
56 md5_byte_t buf[64]; /* accumulate block */
58
59/* Initialize the algorithm. */
60static void md5_init (md5_state_t *pms);
61static void md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes);
62static void md5_finish (md5_state_t *pms, md5_byte_t digest[16]);
63
64static gchar *xmms_bindata_build_path (xmms_bindata_t *bindata, const gchar *hash);
65
66static gchar *xmms_bindata_client_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err);
67static xmmsv_t *xmms_bindata_client_retrieve (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *err);
68static void xmms_bindata_client_remove (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *);
69static GList *xmms_bindata_client_list (xmms_bindata_t *bindata, xmms_error_t *err);
70static gboolean _xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err);
71
72#include "bindata_ipc.c"
73
76{
77 gchar *tmp;
78 xmms_bindata_t *obj;
80
81 obj = xmms_object_new (xmms_bindata_t, xmms_bindata_destroy);
82
83 xmms_bindata_register_ipc_commands (XMMS_OBJECT (obj));
84
85 tmp = XMMS_BUILD_PATH ("bindata");
86 cv = xmms_config_property_register ("bindata.path", tmp, NULL, NULL);
87 g_free (tmp);
88
89 obj->bindir = xmms_config_property_get_string (cv);
90
91 if (!g_file_test (obj->bindir, G_FILE_TEST_IS_DIR)) {
92 if (g_mkdir_with_parents (obj->bindir, 0755) == -1) {
93 xmms_log_error ("Couldn't create bindir %s", obj->bindir);
94 }
95 }
96
97 global_bindata = obj;
98
99 return obj;
100}
101
102static void
103xmms_bindata_destroy (xmms_object_t *obj)
104{
105 xmms_bindata_unregister_ipc_commands ();
106}
107
108gchar *
109xmms_bindata_calculate_md5 (const guchar *data, gsize size, gchar ret[33])
110{
111 md5_state_t state;
112 md5_byte_t digest[16];
113 int di;
114 static gchar hex[] = {
115 '0', '1', '2', '3', '4', '5', '6', '7',
116 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
117 };
118
119 md5_init (&state);
120 md5_append (&state, (const md5_byte_t *)data, size);
121 md5_finish (&state, digest);
122
123 for (di = 0; di < 16; ++di) {
124 ret[di * 2] = hex[digest[di] >> 4];
125 ret[di * 2 + 1] = hex[digest[di] & 0x0f];
126 }
127 ret[32] = 0;
128 return ret;
129}
130
131static gchar *
132xmms_bindata_build_path (xmms_bindata_t *bindata, const gchar *hash)
133{
134 return g_build_path (G_DIR_SEPARATOR_S, bindata->bindir, hash, NULL);
135}
136
137/** Add binary data from a plugin */
138gboolean
139xmms_bindata_plugin_add (const guchar *data, gsize size, gchar hash[33])
140{
141 xmms_error_t err;
142 return _xmms_bindata_add (global_bindata, data, size, hash, &err);
143}
144
145static gboolean
146_xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err)
147{
148 const guchar *ptr;
149 gsize left;
150 gchar *path;
151 FILE *fp;
152
153 xmms_bindata_calculate_md5 (data, len, hash);
154
155 path = xmms_bindata_build_path (bindata, hash);
156
157 if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
158 XMMS_DBG ("file %s is already in bindata dir", hash);
159 g_free (path);
160 return TRUE;
161 }
162
163 XMMS_DBG ("Creating %s", path);
164 fp = fopen (path, "wb");
165 if (!fp) {
166 xmms_log_error ("Couldn't create %s", path);
167 xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't create file on server!");
168 g_free (path);
169 return FALSE;
170 }
171
172 /* write the data to the file */
173 ptr = data;
174 left = len;
175
176 while (left > 0) {
177 size_t w;
178
179 w = fwrite (ptr, 1, left, fp);
180 if (!w && ferror (fp)) {
181 fclose (fp);
182 unlink (path);
183
184 xmms_log_error ("Couldn't write data");
185 xmms_error_set (err, XMMS_ERROR_GENERIC,
186 "Couldn't write data!");
187 g_free (path);
188 return FALSE;
189 }
190
191 left -= w;
192 ptr += w;
193 }
194
195 fclose (fp);
196 g_free (path);
197
198 return TRUE;
199}
200
201char *
202xmms_bindata_client_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err)
203{
204 gchar hash[33];
205 if (_xmms_bindata_add (bindata, (guchar *)data->str, data->len, hash, err))
206 return g_strdup (hash);
207 return NULL;
208}
209
210static xmmsv_t *
211xmms_bindata_client_retrieve (xmms_bindata_t *bindata, const gchar *hash,
212 xmms_error_t *err)
213{
214 xmmsv_t *res;
215 gchar *path;
216 GString *str;
217 FILE *fp;
218
219 path = xmms_bindata_build_path (bindata, hash);
220
221 fp = fopen (path, "rb");
222 if (!fp) {
223 xmms_log_error ("Requesting '%s' which is not on the server", hash);
224 xmms_error_set (err, XMMS_ERROR_NOENT, "File not found!");
225 g_free (path);
226 return NULL;
227 }
228
229 g_free (path);
230
231 str = g_string_new (NULL);
232 while (!feof (fp)) {
233 gchar buf[1024];
234 gint l;
235
236 l = fread (buf, 1, 1024, fp);
237 if (ferror (fp)) {
238 g_string_free (str, TRUE);
239 xmms_log_error ("Error reading bindata '%s'", hash);
240 xmms_error_set (err, XMMS_ERROR_GENERIC, "Error reading file");
241 fclose (fp);
242 return NULL;
243 }
244 g_string_append_len (str, buf, l);
245 }
246
247 fclose (fp);
248
249 res = xmmsv_new_bin ((unsigned char *)str->str, str->len);
250
251 g_string_free (str, TRUE);
252
253 return res;
254}
255
256static void
257xmms_bindata_client_remove (xmms_bindata_t *bindata, const gchar *hash,
258 xmms_error_t *err)
259{
260 gchar *path;
261 path = xmms_bindata_build_path (bindata, hash);
262 if (unlink (path) == -1) {
263 xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't remove file");
264 }
265 g_free (path);
266 return;
267}
268
269static GList *
270xmms_bindata_client_list (xmms_bindata_t *bindata, xmms_error_t *err)
271{
272 GList *entries = NULL;
273 gchar *path;
274 const gchar *file;
275 GDir *dir;
276
277 path = xmms_bindata_build_path (bindata, NULL);
278 dir = g_dir_open (path, 0, NULL);
279 g_free (path);
280
281 if (!dir) {
282 xmms_error_set (err, XMMS_ERROR_GENERIC,
283 "Couldn't open bindata directory");
284 return NULL;
285 }
286
287 while ((file = g_dir_read_name (dir))) {
288 entries = g_list_prepend (entries, xmmsv_new_string (file));
289 }
290
291 g_dir_close (dir);
292
293 return entries;
294}
295
296/*
297 Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
298
299 This software is provided 'as-is', without any express or implied
300 warranty. In no event will the authors be held liable for any damages
301 arising from the use of this software.
302
303 Permission is granted to anyone to use this software for any purpose,
304 including commercial applications, and to alter it and redistribute it
305 freely, subject to the following restrictions:
306
307 1. The origin of this software must not be misrepresented; you must not
308 claim that you wrote the original software. If you use this software
309 in a product, an acknowledgment in the product documentation would be
310 appreciated but is not required.
311 2. Altered source versions must be plainly marked as such, and must not be
312 misrepresented as being the original software.
313 3. This notice may not be removed or altered from any source distribution.
314
315 L. Peter Deutsch
316 ghost@aladdin.com
317
318 */
319/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
320/*
321 Independent implementation of MD5 (RFC 1321).
322
323 This code implements the MD5 Algorithm defined in RFC 1321, whose
324 text is available at
325 http://www.ietf.org/rfc/rfc1321.txt
326 The code is derived from the text of the RFC, including the test suite
327 (section A.5) but excluding the rest of Appendix A. It does not include
328 any code or documentation that is identified in the RFC as being
329 copyrighted.
330
331 The original and principal author of md5.c is L. Peter Deutsch
332 <ghost@aladdin.com>. Other authors are noted in the change history
333 that follows (in reverse chronological order):
334
335 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
336 either statically or dynamically; added missing #include <string.h>
337 in library.
338 2002-03-11 lpd Corrected argument list for main(), and added int return
339 type, in test program and T value program.
340 2002-02-21 lpd Added missing #include <stdio.h> in test program.
341 2000-07-03 lpd Patched to eliminate warnings about "constant is
342 unsigned in ANSI C, signed in traditional"; made test program
343 self-checking.
344 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
345 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
346 1999-05-03 lpd Original version.
347 */
348
349/*
350 * This package supports both compile-time and run-time determination of CPU
351 * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
352 * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
353 * defined as non-zero, the code will be compiled to run only on big-endian
354 * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
355 * run on either big- or little-endian CPUs, but will run slightly less
356 * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
357 */
358
359#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
360#ifdef ARCH_IS_BIG_ENDIAN
361# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
362#else
363# define BYTE_ORDER 0
364#endif
365
366#define T_MASK ((md5_word_t)~0)
367#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
368#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
369#define T3 0x242070db
370#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
371#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
372#define T6 0x4787c62a
373#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
374#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
375#define T9 0x698098d8
376#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
377#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
378#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
379#define T13 0x6b901122
380#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
381#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
382#define T16 0x49b40821
383#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
384#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
385#define T19 0x265e5a51
386#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
387#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
388#define T22 0x02441453
389#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
390#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
391#define T25 0x21e1cde6
392#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
393#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
394#define T28 0x455a14ed
395#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
396#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
397#define T31 0x676f02d9
398#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
399#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
400#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
401#define T35 0x6d9d6122
402#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
403#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
404#define T38 0x4bdecfa9
405#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
406#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
407#define T41 0x289b7ec6
408#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
409#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
410#define T44 0x04881d05
411#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
412#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
413#define T47 0x1fa27cf8
414#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
415#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
416#define T50 0x432aff97
417#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
418#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
419#define T53 0x655b59c3
420#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
421#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
422#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
423#define T57 0x6fa87e4f
424#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
425#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
426#define T60 0x4e0811a1
427#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
428#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
429#define T63 0x2ad7d2bb
430#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
431
432
433static void
434md5_process (md5_state_t *pms, const md5_byte_t *data /*[64]*/)
435{
437 a = pms->abcd[0], b = pms->abcd[1],
438 c = pms->abcd[2], d = pms->abcd[3];
439 md5_word_t t;
440#if BYTE_ORDER > 0
441 /* Define storage only for big-endian CPUs. */
442 md5_word_t X[16];
443#else
444 /* Define storage for little-endian or both types of CPUs. */
445 md5_word_t xbuf[16];
446 const md5_word_t *X;
447#endif
448
449 {
450#if BYTE_ORDER == 0
451 /*
452 * Determine dynamically whether this is a big-endian or
453 * little-endian machine, since we can use a more efficient
454 * algorithm on the latter.
455 */
456 static const int w = 1;
457
458 if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
459#endif
460#if BYTE_ORDER <= 0 /* little-endian */
461 {
462 /*
463 * On little-endian machines, we can process properly aligned
464 * data without copying it.
465 */
466 if (!((data - (const md5_byte_t *)0) & 3)) {
467 /* data are properly aligned */
468 X = (const md5_word_t *)data;
469 } else {
470 /* not aligned */
471 memcpy (xbuf, data, 64);
472 X = xbuf;
473 }
474 }
475#endif
476#if BYTE_ORDER == 0
477 else /* dynamic big-endian */
478#endif
479#if BYTE_ORDER >= 0 /* big-endian */
480 {
481 /*
482 * On big-endian machines, we must arrange the bytes in the
483 * right order.
484 */
485 const md5_byte_t *xp = data;
486 int i;
487
488# if BYTE_ORDER == 0
489 X = xbuf;/* (dynamic only) */
490# else
491# define xbuf X /* (static only) */
492# endif
493 for (i = 0; i < 16; ++i, xp += 4)
494 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
495 }
496#endif
497 }
498
499#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
500
501 /* Round 1. */
502 /* Let [abcd k s i] denote the operation
503 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
504#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
505#define SET(a, b, c, d, k, s, Ti)\
506 t = a + F (b,c,d) + X[k] + Ti;\
507 a = ROTATE_LEFT (t, s) + b
508 /* Do the following 16 operations. */
509 SET (a, b, c, d, 0, 7, T1);
510 SET (d, a, b, c, 1, 12, T2);
511 SET (c, d, a, b, 2, 17, T3);
512 SET (b, c, d, a, 3, 22, T4);
513 SET (a, b, c, d, 4, 7, T5);
514 SET (d, a, b, c, 5, 12, T6);
515 SET (c, d, a, b, 6, 17, T7);
516 SET (b, c, d, a, 7, 22, T8);
517 SET (a, b, c, d, 8, 7, T9);
518 SET (d, a, b, c, 9, 12, T10);
519 SET (c, d, a, b, 10, 17, T11);
520 SET (b, c, d, a, 11, 22, T12);
521 SET (a, b, c, d, 12, 7, T13);
522 SET (d, a, b, c, 13, 12, T14);
523 SET (c, d, a, b, 14, 17, T15);
524 SET (b, c, d, a, 15, 22, T16);
525#undef SET
526
527 /* Round 2. */
528 /* Let [abcd k s i] denote the operation
529 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
530#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
531#define SET(a, b, c, d, k, s, Ti)\
532 t = a + G (b,c,d) + X[k] + Ti;\
533 a = ROTATE_LEFT (t, s) + b
534 /* Do the following 16 operations. */
535 SET (a, b, c, d, 1, 5, T17);
536 SET (d, a, b, c, 6, 9, T18);
537 SET (c, d, a, b, 11, 14, T19);
538 SET (b, c, d, a, 0, 20, T20);
539 SET (a, b, c, d, 5, 5, T21);
540 SET (d, a, b, c, 10, 9, T22);
541 SET (c, d, a, b, 15, 14, T23);
542 SET (b, c, d, a, 4, 20, T24);
543 SET (a, b, c, d, 9, 5, T25);
544 SET (d, a, b, c, 14, 9, T26);
545 SET (c, d, a, b, 3, 14, T27);
546 SET (b, c, d, a, 8, 20, T28);
547 SET (a, b, c, d, 13, 5, T29);
548 SET (d, a, b, c, 2, 9, T30);
549 SET (c, d, a, b, 7, 14, T31);
550 SET (b, c, d, a, 12, 20, T32);
551#undef SET
552
553 /* Round 3. */
554 /* Let [abcd k s t] denote the operation
555 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
556#define H(x, y, z) ((x) ^ (y) ^ (z))
557#define SET(a, b, c, d, k, s, Ti)\
558 t = a + H (b,c,d) + X[k] + Ti;\
559 a = ROTATE_LEFT (t, s) + b
560 /* Do the following 16 operations. */
561 SET (a, b, c, d, 5, 4, T33);
562 SET (d, a, b, c, 8, 11, T34);
563 SET (c, d, a, b, 11, 16, T35);
564 SET (b, c, d, a, 14, 23, T36);
565 SET (a, b, c, d, 1, 4, T37);
566 SET (d, a, b, c, 4, 11, T38);
567 SET (c, d, a, b, 7, 16, T39);
568 SET (b, c, d, a, 10, 23, T40);
569 SET (a, b, c, d, 13, 4, T41);
570 SET (d, a, b, c, 0, 11, T42);
571 SET (c, d, a, b, 3, 16, T43);
572 SET (b, c, d, a, 6, 23, T44);
573 SET (a, b, c, d, 9, 4, T45);
574 SET (d, a, b, c, 12, 11, T46);
575 SET (c, d, a, b, 15, 16, T47);
576 SET (b, c, d, a, 2, 23, T48);
577#undef SET
578
579 /* Round 4. */
580 /* Let [abcd k s t] denote the operation
581 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
582#define I(x, y, z) ((y) ^ ((x) | ~(z)))
583#define SET(a, b, c, d, k, s, Ti)\
584 t = a + I (b,c,d) + X[k] + Ti;\
585 a = ROTATE_LEFT (t, s) + b
586 /* Do the following 16 operations. */
587 SET (a, b, c, d, 0, 6, T49);
588 SET (d, a, b, c, 7, 10, T50);
589 SET (c, d, a, b, 14, 15, T51);
590 SET (b, c, d, a, 5, 21, T52);
591 SET (a, b, c, d, 12, 6, T53);
592 SET (d, a, b, c, 3, 10, T54);
593 SET (c, d, a, b, 10, 15, T55);
594 SET (b, c, d, a, 1, 21, T56);
595 SET (a, b, c, d, 8, 6, T57);
596 SET (d, a, b, c, 15, 10, T58);
597 SET (c, d, a, b, 6, 15, T59);
598 SET (b, c, d, a, 13, 21, T60);
599 SET (a, b, c, d, 4, 6, T61);
600 SET (d, a, b, c, 11, 10, T62);
601 SET (c, d, a, b, 2, 15, T63);
602 SET (b, c, d, a, 9, 21, T64);
603#undef SET
604
605 /* Then perform the following additions. (That is increment each
606 of the four registers by the value it had before this block
607 was started.) */
608 pms->abcd[0] += a;
609 pms->abcd[1] += b;
610 pms->abcd[2] += c;
611 pms->abcd[3] += d;
612}
613
614static void
615md5_init (md5_state_t *pms)
616{
617 pms->count[0] = pms->count[1] = 0;
618 pms->abcd[0] = 0x67452301;
619 pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
620 pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
621 pms->abcd[3] = 0x10325476;
622}
623
624static void
625md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes)
626{
627 const md5_byte_t *p = data;
628 int left = nbytes;
629 int offset = (pms->count[0] >> 3) & 63;
630 md5_word_t nbits = (md5_word_t)(nbytes << 3);
631
632 if (nbytes <= 0)
633 return;
634
635 /* Update the message length. */
636 pms->count[1] += nbytes >> 29;
637 pms->count[0] += nbits;
638 if (pms->count[0] < nbits)
639 pms->count[1]++;
640
641 /* Process an initial partial block. */
642 if (offset) {
643 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
644
645 memcpy (pms->buf + offset, p, copy);
646 if (offset + copy < 64)
647 return;
648 p += copy;
649 left -= copy;
650 md5_process (pms, pms->buf);
651 }
652
653 /* Process full blocks. */
654 for (; left >= 64; p += 64, left -= 64)
655 md5_process (pms, p);
656
657 /* Process a final partial block. */
658 if (left)
659 memcpy (pms->buf, p, left);
660}
661
662static void
663md5_finish (md5_state_t *pms, md5_byte_t digest[16])
664{
665 static const md5_byte_t pad[64] = {
666 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
667 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
668 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
669 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
670 };
671 md5_byte_t data[8];
672 int i;
673
674 /* Save the length before padding. */
675 for (i = 0; i < 8; ++i)
676 data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
677 /* Pad to 56 bytes mod 64. */
678 md5_append (pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
679 /* Append the length. */
680 md5_append (pms, data, 8);
681 for (i = 0; i < 16; ++i)
682 digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
683}
#define T51
Definition: bindata.c:417
#define T46
Definition: bindata.c:412
#define T50
Definition: bindata.c:416
#define T45
Definition: bindata.c:411
#define T56
Definition: bindata.c:422
#define T17
Definition: bindata.c:383
#define T54
Definition: bindata.c:420
#define T20
Definition: bindata.c:386
#define T43
Definition: bindata.c:409
#define T9
Definition: bindata.c:375
#define T14
Definition: bindata.c:380
#define T57
Definition: bindata.c:423
#define T37
Definition: bindata.c:403
#define T2
Definition: bindata.c:368
#define T_MASK
Definition: bindata.c:366
#define T7
Definition: bindata.c:373
#define T61
Definition: bindata.c:427
#define T10
Definition: bindata.c:376
#define T31
Definition: bindata.c:397
#define T62
Definition: bindata.c:428
#define T26
Definition: bindata.c:392
#define T24
Definition: bindata.c:390
#define T44
Definition: bindata.c:410
#define T25
Definition: bindata.c:391
struct md5_state_s md5_state_t
#define T36
Definition: bindata.c:402
unsigned int md5_word_t
Definition: bindata.c:50
#define T18
Definition: bindata.c:384
#define T21
Definition: bindata.c:387
#define T6
Definition: bindata.c:372
#define T3
Definition: bindata.c:369
#define T58
Definition: bindata.c:424
#define SET(a, b, c, d, k, s, Ti)
#define T29
Definition: bindata.c:395
#define T60
Definition: bindata.c:426
#define T59
Definition: bindata.c:425
#define T5
Definition: bindata.c:371
#define T53
Definition: bindata.c:419
#define T39
Definition: bindata.c:405
#define T38
Definition: bindata.c:404
#define T19
Definition: bindata.c:385
#define T33
Definition: bindata.c:399
unsigned char md5_byte_t
Definition: bindata.c:49
gboolean xmms_bindata_plugin_add(const guchar *data, gsize size, gchar hash[33])
Add binary data from a plugin.
Definition: bindata.c:139
#define T49
Definition: bindata.c:415
#define T16
Definition: bindata.c:382
#define T22
Definition: bindata.c:388
#define T55
Definition: bindata.c:421
#define T41
Definition: bindata.c:407
#define T48
Definition: bindata.c:414
#define T4
Definition: bindata.c:370
#define T64
Definition: bindata.c:430
#define T40
Definition: bindata.c:406
#define T47
Definition: bindata.c:413
#define T13
Definition: bindata.c:379
gchar * xmms_bindata_calculate_md5(const guchar *data, gsize size, gchar ret[33])
Definition: bindata.c:109
#define T30
Definition: bindata.c:396
#define T11
Definition: bindata.c:377
#define T63
Definition: bindata.c:429
#define T1
Definition: bindata.c:367
#define T35
Definition: bindata.c:401
#define T8
Definition: bindata.c:374
#define T23
Definition: bindata.c:389
#define T42
Definition: bindata.c:408
xmms_bindata_t * xmms_bindata_init()
Definition: bindata.c:75
#define T15
Definition: bindata.c:381
#define T34
Definition: bindata.c:400
#define T27
Definition: bindata.c:393
#define T28
Definition: bindata.c:394
#define T52
Definition: bindata.c:418
#define T32
Definition: bindata.c:398
#define T12
Definition: bindata.c:378
xmms_config_property_t * xmms_config_property_register(const gchar *path, const gchar *default_value, xmms_object_handler_t cb, gpointer userdata)
Register a new config property.
Definition: config.c:334
const gchar * xmms_config_property_get_string(const xmms_config_property_t *prop)
Return the value of a config property as a string.
Definition: config.c:243
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
Definition: value.c:180
struct xmmsv_St xmmsv_t
Definition: xmmsv_general.h:48
xmmsv_t * xmmsv_new_bin(const unsigned char *data, unsigned int len)
Allocates a new binary data xmmsv_t.
Definition: value.c:225
struct xmms_bindata_St xmms_bindata_t
Definition: xmms_bindata.h:20
struct xmms_config_property_St xmms_config_property_t
Definition: xmms_config.h:26
#define xmms_log_error(fmt,...)
Definition: xmms_log.h:35
#define XMMS_DBG(fmt,...)
Definition: xmms_log.h:32
G_BEGIN_DECLS struct xmms_error_St xmms_error_t
#define xmms_object_new(objtype, destroyfunc)
Definition: xmms_object.h:115
#define XMMS_OBJECT(p)
Definition: xmms_object.h:77
#define XMMS_BUILD_PATH(...)
Definition: xmms_utils.h:4
@ XMMS_ERROR_GENERIC
@ XMMS_ERROR_NOENT