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