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 
25 #include "xmmsc/xmmsc_idnumbers.h"
27 #include "xmmsc/xmmsc_ipc_msg.h"
28 
29 #include "xmms/xmms_log.h"
30 
31 #include "xmms/xmms_bindata.h"
32 
33 #include "xmmspriv/xmms_ringbuf.h"
34 #include "xmmspriv/xmms_ipc.h"
35 #include "xmmspriv/xmms_playlist.h"
36 #include "xmmspriv/xmms_config.h"
37 #include "xmmspriv/xmms_bindata.h"
38 #include "xmmspriv/xmms_utils.h"
39 
40 struct xmms_bindata_St {
41  xmms_object_t obj;
42  const gchar *bindir;
43 };
44 
45 static xmms_bindata_t *global_bindata;
46 
47 static void xmms_bindata_destroy (xmms_object_t *obj);
48 
49 typedef unsigned char md5_byte_t; /* 8-bit byte */
50 typedef unsigned int md5_word_t; /* 32-bit word */
51 
52 /* Define the state of the MD5 Algorithm. */
53 typedef 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 */
57 } md5_state_t;
58 
59 /* Initialize the algorithm. */
60 static void md5_init (md5_state_t *pms);
61 static void md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes);
62 static void md5_finish (md5_state_t *pms, md5_byte_t digest[16]);
63 
64 static gchar *xmms_bindata_build_path (xmms_bindata_t *bindata, const gchar *hash);
65 
66 static gchar *xmms_bindata_client_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err);
67 static xmmsv_t *xmms_bindata_client_retrieve (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *err);
68 static void xmms_bindata_client_remove (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *);
69 static GList *xmms_bindata_client_list (xmms_bindata_t *bindata, xmms_error_t *err);
70 static 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 
102 static void
103 xmms_bindata_destroy (xmms_object_t *obj)
104 {
105  xmms_bindata_unregister_ipc_commands ();
106 }
107 
108 gchar *
109 xmms_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 
131 static gchar *
132 xmms_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 */
138 gboolean
139 xmms_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 
145 static 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 
201 char *
202 xmms_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 
210 static xmmsv_t *
211 xmms_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 
256 static void
257 xmms_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 
269 static GList *
270 xmms_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 
433 static void
434 md5_process (md5_state_t *pms, const md5_byte_t *data /*[64]*/)
435 {
436  md5_word_t
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 
614 static void
615 md5_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 
624 static void
625 md5_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 
662 static void
663 md5_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 T24
Definition: bindata.c:390
#define T17
Definition: bindata.c:383
#define T28
Definition: bindata.c:394
#define T31
Definition: bindata.c:397
#define T54
Definition: bindata.c:420
#define XMMS_OBJECT(p)
Definition: xmms_object.h:77
#define T14
Definition: bindata.c:380
#define T8
Definition: bindata.c:374
#define T3
Definition: bindata.c:369
#define T7
Definition: bindata.c:373
#define T9
Definition: bindata.c:375
#define T2
Definition: bindata.c:368
struct xmmsv_St xmmsv_t
Definition: xmmsv_general.h:48
#define T35
Definition: bindata.c:401
#define T15
Definition: bindata.c:381
#define T4
Definition: bindata.c:370
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
Definition: value.c:180
#define T57
Definition: bindata.c:423
#define T34
Definition: bindata.c:400
#define T36
Definition: bindata.c:402
#define T52
Definition: bindata.c:418
unsigned char md5_byte_t
Definition: bindata.c:49
#define T39
Definition: bindata.c:405
#define T19
Definition: bindata.c:385
#define T25
Definition: bindata.c:391
#define T30
Definition: bindata.c:396
#define T10
Definition: bindata.c:376
#define T12
Definition: bindata.c:378
#define T29
Definition: bindata.c:395
#define T26
Definition: bindata.c:392
#define T47
Definition: bindata.c:413
#define T33
Definition: bindata.c:399
#define T38
Definition: bindata.c:404
#define xmms_log_error(fmt,...)
Definition: xmms_log.h:35
#define T45
Definition: bindata.c:411
#define T60
Definition: bindata.c:426
#define T63
Definition: bindata.c:429
#define T16
Definition: bindata.c:382
#define T11
Definition: bindata.c:377
#define T56
Definition: bindata.c:422
#define T41
Definition: bindata.c:407
#define T40
Definition: bindata.c:406
#define T49
Definition: bindata.c:415
#define T46
Definition: bindata.c:412
#define T51
Definition: bindata.c:417
#define T42
Definition: bindata.c:408
#define T58
Definition: bindata.c:424
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
#define T37
Definition: bindata.c:403
gboolean xmms_bindata_plugin_add(const guchar *data, gsize size, gchar hash[33])
Add binary data from a plugin.
Definition: bindata.c:139
gchar * xmms_bindata_calculate_md5(const guchar *data, gsize size, gchar ret[33])
Definition: bindata.c:109
#define T43
Definition: bindata.c:409
#define T53
Definition: bindata.c:419
#define T20
Definition: bindata.c:386
#define T64
Definition: bindata.c:430
#define T55
Definition: bindata.c:421
#define T32
Definition: bindata.c:398
#define T1
Definition: bindata.c:367
#define T61
Definition: bindata.c:427
#define T62
Definition: bindata.c:428
#define XMMS_DBG(fmt,...)
Definition: xmms_log.h:32
struct md5_state_s md5_state_t
#define T23
Definition: bindata.c:389
#define xmms_object_new(objtype, destroyfunc)
Definition: xmms_object.h:115
G_BEGIN_DECLS struct xmms_error_St xmms_error_t
#define T50
Definition: bindata.c:416
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
xmms_bindata_t * xmms_bindata_init()
Definition: bindata.c:75
#define T48
Definition: bindata.c:414
struct xmms_config_property_St xmms_config_property_t
Definition: xmms_config.h:26
#define T27
Definition: bindata.c:393
#define T44
Definition: bindata.c:410
#define T21
Definition: bindata.c:387
xmmsv_t * xmmsv_new_bin(const unsigned char *data, unsigned int len)
Allocates a new binary data xmmsv_t.
Definition: value.c:225
#define T_MASK
Definition: bindata.c:366
#define XMMS_BUILD_PATH(...)
Definition: xmms_utils.h:4
#define T22
Definition: bindata.c:388
#define T59
Definition: bindata.c:425
#define SET(a, b, c, d, k, s, Ti)
#define T6
Definition: bindata.c:372
unsigned int md5_word_t
Definition: bindata.c:50
#define T5
Definition: bindata.c:371
struct xmms_bindata_St xmms_bindata_t
Definition: xmms_bindata.h:20
#define T13
Definition: bindata.c:379
#define T18
Definition: bindata.c:384