00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <glib.h>
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <unistd.h>
00022 #include <sys/time.h>
00023 #include <errno.h>
00024
00025 #include "xmmsc/xmmsc_idnumbers.h"
00026 #include "xmmsc/xmmsc_ipc_transport.h"
00027 #include "xmmsc/xmmsc_ipc_msg.h"
00028
00029 #include "xmms/xmms_log.h"
00030
00031 #include "xmmspriv/xmms_ringbuf.h"
00032 #include "xmmspriv/xmms_ipc.h"
00033 #include "xmmspriv/xmms_playlist.h"
00034 #include "xmmspriv/xmms_config.h"
00035 #include "xmmspriv/xmms_bindata.h"
00036 #include "xmmspriv/xmms_utils.h"
00037
00038 struct xmms_bindata_St {
00039 xmms_object_t obj;
00040 const gchar *bindir;
00041 };
00042
00043 static xmms_bindata_t *global_bindata;
00044
00045 static void xmms_bindata_destroy (xmms_object_t *obj);
00046
00047 typedef unsigned char md5_byte_t;
00048 typedef unsigned int md5_word_t;
00049
00050
00051 typedef struct md5_state_s {
00052 md5_word_t count[2];
00053 md5_word_t abcd[4];
00054 md5_byte_t buf[64];
00055 } md5_state_t;
00056
00057
00058 static void md5_init (md5_state_t *pms);
00059 static void md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes);
00060 static void md5_finish (md5_state_t *pms, md5_byte_t digest[16]);
00061
00062 static gchar *xmms_bindata_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err);
00063 static GString *xmms_bindata_retrieve (xmms_bindata_t *bindata, gchar *hash, xmms_error_t *err);
00064 static void xmms_bindata_remove (xmms_bindata_t *bindata, gchar *hash, xmms_error_t *);
00065 static GList *xmms_bindata_list (xmms_bindata_t *bindata, xmms_error_t *err);
00066 static gboolean _xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err);
00067
00068 XMMS_CMD_DEFINE (get_data, xmms_bindata_retrieve, xmms_bindata_t *, BIN, STRING, NONE);
00069 XMMS_CMD_DEFINE (add_data, xmms_bindata_add, xmms_bindata_t *, STRING, BIN, NONE);
00070 XMMS_CMD_DEFINE (remove_data, xmms_bindata_remove, xmms_bindata_t *, NONE, STRING, NONE);
00071 XMMS_CMD_DEFINE (list_data, xmms_bindata_list, xmms_bindata_t *, LIST, NONE, NONE);
00072
00073 xmms_bindata_t *
00074 xmms_bindata_init ()
00075 {
00076 gchar *tmp;
00077 xmms_bindata_t *obj;
00078 xmms_config_property_t *cv;
00079
00080 obj = xmms_object_new (xmms_bindata_t, xmms_bindata_destroy);
00081
00082 xmms_object_cmd_add (XMMS_OBJECT (obj),
00083 XMMS_IPC_CMD_ADD_DATA,
00084 XMMS_CMD_FUNC (add_data));
00085
00086 xmms_object_cmd_add (XMMS_OBJECT (obj),
00087 XMMS_IPC_CMD_REMOVE_DATA,
00088 XMMS_CMD_FUNC (remove_data));
00089
00090 xmms_object_cmd_add (XMMS_OBJECT (obj),
00091 XMMS_IPC_CMD_GET_DATA,
00092 XMMS_CMD_FUNC (get_data));
00093
00094 xmms_object_cmd_add (XMMS_OBJECT (obj),
00095 XMMS_IPC_CMD_LIST_DATA,
00096 XMMS_CMD_FUNC (list_data));
00097
00098 xmms_ipc_object_register (XMMS_IPC_OBJECT_BINDATA, XMMS_OBJECT (obj));
00099
00100 tmp = XMMS_BUILD_PATH ("bindata");
00101 cv = xmms_config_property_register ("bindata.path", tmp, NULL, NULL);
00102 g_free (tmp);
00103
00104 obj->bindir = xmms_config_property_get_string (cv);
00105
00106 if (!g_file_test (obj->bindir, G_FILE_TEST_IS_DIR)) {
00107 if (g_mkdir_with_parents (obj->bindir, 0755) == -1) {
00108 xmms_log_error ("Couldn't create bindir %s", obj->bindir);
00109 }
00110 }
00111
00112 global_bindata = obj;
00113
00114 return obj;
00115 }
00116
00117 static void
00118 xmms_bindata_destroy (xmms_object_t *obj)
00119 {
00120 xmms_ipc_object_unregister (XMMS_IPC_OBJECT_BINDATA);
00121 }
00122
00123 gchar *
00124 xmms_bindata_calculate_md5 (const guchar *data, guint size, gchar ret[33])
00125 {
00126 md5_state_t state;
00127 md5_byte_t digest[16];
00128 int di;
00129 static gchar hex[] = {
00130 '0', '1', '2', '3', '4', '5', '6', '7',
00131 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
00132 };
00133
00134 md5_init (&state);
00135 md5_append (&state, (const md5_byte_t *)data, size);
00136 md5_finish (&state, digest);
00137
00138 for (di = 0; di < 16; ++di) {
00139 ret[di * 2] = hex[digest[di] >> 4];
00140 ret[di * 2 + 1] = hex[digest[di] & 0x0f];
00141 }
00142 ret[32] = 0;
00143 return ret;
00144 }
00145
00146
00147 gboolean
00148 xmms_bindata_plugin_add (const guchar *data, gsize size, gchar hash[33])
00149 {
00150 xmms_error_t err;
00151 return _xmms_bindata_add (global_bindata, data, size, hash, &err);
00152 }
00153
00154 static gboolean
00155 _xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err)
00156 {
00157 const guchar *ptr;
00158 gsize left;
00159 gchar *path;
00160 FILE *fp;
00161
00162 xmms_bindata_calculate_md5 (data, len, hash);
00163
00164 path = XMMS_BUILD_PATH ("bindata", hash);
00165
00166 if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
00167 XMMS_DBG ("file %s is already in bindata dir", hash);
00168 g_free (path);
00169 return TRUE;
00170 }
00171
00172 XMMS_DBG ("Creating %s", path);
00173 fp = fopen (path, "wb");
00174 if (!fp) {
00175 xmms_log_error ("Couldn't create %s", path);
00176 xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't create file on server!");
00177 g_free (path);
00178 return FALSE;
00179 }
00180
00181
00182 ptr = data;
00183 left = len;
00184
00185 while (left > 0) {
00186 size_t w;
00187
00188 w = fwrite (ptr, 1, left, fp);
00189 if (!w && ferror (fp)) {
00190 fclose (fp);
00191 unlink (path);
00192
00193 xmms_log_error ("Couldn't write data");
00194 xmms_error_set (err, XMMS_ERROR_GENERIC,
00195 "Couldn't write data!");
00196 g_free (path);
00197 return FALSE;
00198 }
00199
00200 left -= w;
00201 ptr += w;
00202 }
00203
00204 fclose (fp);
00205 g_free (path);
00206
00207 return TRUE;
00208 }
00209
00210 char *
00211 xmms_bindata_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err)
00212 {
00213 gchar hash[33];
00214 if (_xmms_bindata_add (bindata, (guchar *)data->str, data->len, hash, err))
00215 return g_strdup (hash);
00216 return NULL;
00217 }
00218
00219 static GString *
00220 xmms_bindata_retrieve (xmms_bindata_t *bindata, gchar *hash, xmms_error_t *err)
00221 {
00222 gchar *path;
00223 GString *str;
00224 FILE *fp;
00225
00226 path = XMMS_BUILD_PATH ("bindata", hash);
00227
00228 fp = fopen (path, "rb");
00229 if (!fp) {
00230 xmms_log_error ("Requesting '%s' which is not on the server", hash);
00231 xmms_error_set (err, XMMS_ERROR_NOENT, "File not found!");
00232 g_free (path);
00233 return NULL;
00234 }
00235
00236 g_free (path);
00237
00238 str = g_string_new (NULL);
00239 while (!feof (fp)) {
00240 gchar buf[1024];
00241 gint l;
00242
00243 l = fread (buf, 1, 1024, fp);
00244 if (ferror (fp)) {
00245 g_string_free (str, TRUE);
00246 xmms_log_error ("Error reading bindata '%s'", hash);
00247 xmms_error_set (err, XMMS_ERROR_GENERIC, "Error reading file");
00248 return NULL;
00249 }
00250 g_string_append_len (str, buf, l);
00251 }
00252
00253 fclose (fp);
00254
00255 return str;
00256 }
00257
00258 static void
00259 xmms_bindata_remove (xmms_bindata_t *bindata, gchar *hash, xmms_error_t *err)
00260 {
00261 gchar *path;
00262 path = XMMS_BUILD_PATH ("bindata", hash);
00263 if (unlink (path) == -1) {
00264 xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't remove file");
00265 }
00266 g_free (path);
00267 return;
00268 }
00269
00270 static GList *
00271 xmms_bindata_list (xmms_bindata_t *bindata, xmms_error_t *err)
00272 {
00273 GList *entries = NULL;
00274 gchar *path;
00275 const gchar *file;
00276 GDir *dir;
00277
00278 path = XMMS_BUILD_PATH ("bindata");
00279 dir = g_dir_open (path, 0, NULL);
00280 g_free (path);
00281
00282 if (!dir) {
00283 xmms_error_set (err, XMMS_ERROR_GENERIC,
00284 "Couldn't open bindata directory");
00285 return NULL;
00286 }
00287
00288 while ((file = g_dir_read_name (dir))) {
00289 entries = g_list_prepend (entries,
00290 xmms_object_cmd_value_str_new (file));
00291 }
00292
00293 g_dir_close (dir);
00294
00295 return entries;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 #undef BYTE_ORDER
00362 #ifdef ARCH_IS_BIG_ENDIAN
00363 # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
00364 #else
00365 # define BYTE_ORDER 0
00366 #endif
00367
00368 #define T_MASK ((md5_word_t)~0)
00369 #define T1 (T_MASK ^ 0x28955b87)
00370 #define T2 (T_MASK ^ 0x173848a9)
00371 #define T3 0x242070db
00372 #define T4 (T_MASK ^ 0x3e423111)
00373 #define T5 (T_MASK ^ 0x0a83f050)
00374 #define T6 0x4787c62a
00375 #define T7 (T_MASK ^ 0x57cfb9ec)
00376 #define T8 (T_MASK ^ 0x02b96afe)
00377 #define T9 0x698098d8
00378 #define T10 (T_MASK ^ 0x74bb0850)
00379 #define T11 (T_MASK ^ 0x0000a44e)
00380 #define T12 (T_MASK ^ 0x76a32841)
00381 #define T13 0x6b901122
00382 #define T14 (T_MASK ^ 0x02678e6c)
00383 #define T15 (T_MASK ^ 0x5986bc71)
00384 #define T16 0x49b40821
00385 #define T17 (T_MASK ^ 0x09e1da9d)
00386 #define T18 (T_MASK ^ 0x3fbf4cbf)
00387 #define T19 0x265e5a51
00388 #define T20 (T_MASK ^ 0x16493855)
00389 #define T21 (T_MASK ^ 0x29d0efa2)
00390 #define T22 0x02441453
00391 #define T23 (T_MASK ^ 0x275e197e)
00392 #define T24 (T_MASK ^ 0x182c0437)
00393 #define T25 0x21e1cde6
00394 #define T26 (T_MASK ^ 0x3cc8f829)
00395 #define T27 (T_MASK ^ 0x0b2af278)
00396 #define T28 0x455a14ed
00397 #define T29 (T_MASK ^ 0x561c16fa)
00398 #define T30 (T_MASK ^ 0x03105c07)
00399 #define T31 0x676f02d9
00400 #define T32 (T_MASK ^ 0x72d5b375)
00401 #define T33 (T_MASK ^ 0x0005c6bd)
00402 #define T34 (T_MASK ^ 0x788e097e)
00403 #define T35 0x6d9d6122
00404 #define T36 (T_MASK ^ 0x021ac7f3)
00405 #define T37 (T_MASK ^ 0x5b4115bb)
00406 #define T38 0x4bdecfa9
00407 #define T39 (T_MASK ^ 0x0944b49f)
00408 #define T40 (T_MASK ^ 0x4140438f)
00409 #define T41 0x289b7ec6
00410 #define T42 (T_MASK ^ 0x155ed805)
00411 #define T43 (T_MASK ^ 0x2b10cf7a)
00412 #define T44 0x04881d05
00413 #define T45 (T_MASK ^ 0x262b2fc6)
00414 #define T46 (T_MASK ^ 0x1924661a)
00415 #define T47 0x1fa27cf8
00416 #define T48 (T_MASK ^ 0x3b53a99a)
00417 #define T49 (T_MASK ^ 0x0bd6ddbb)
00418 #define T50 0x432aff97
00419 #define T51 (T_MASK ^ 0x546bdc58)
00420 #define T52 (T_MASK ^ 0x036c5fc6)
00421 #define T53 0x655b59c3
00422 #define T54 (T_MASK ^ 0x70f3336d)
00423 #define T55 (T_MASK ^ 0x00100b82)
00424 #define T56 (T_MASK ^ 0x7a7ba22e)
00425 #define T57 0x6fa87e4f
00426 #define T58 (T_MASK ^ 0x01d3191f)
00427 #define T59 (T_MASK ^ 0x5cfebceb)
00428 #define T60 0x4e0811a1
00429 #define T61 (T_MASK ^ 0x08ac817d)
00430 #define T62 (T_MASK ^ 0x42c50dca)
00431 #define T63 0x2ad7d2bb
00432 #define T64 (T_MASK ^ 0x14792c6e)
00433
00434
00435 static void
00436 md5_process (md5_state_t *pms, const md5_byte_t *data )
00437 {
00438 md5_word_t
00439 a = pms->abcd[0], b = pms->abcd[1],
00440 c = pms->abcd[2], d = pms->abcd[3];
00441 md5_word_t t;
00442 #if BYTE_ORDER > 0
00443
00444 md5_word_t X[16];
00445 #else
00446
00447 md5_word_t xbuf[16];
00448 const md5_word_t *X;
00449 #endif
00450
00451 {
00452 #if BYTE_ORDER == 0
00453
00454
00455
00456
00457
00458 static const int w = 1;
00459
00460 if (*((const md5_byte_t *)&w))
00461 #endif
00462 #if BYTE_ORDER <= 0
00463 {
00464
00465
00466
00467
00468 if (!((data - (const md5_byte_t *)0) & 3)) {
00469
00470 X = (const md5_word_t *)data;
00471 } else {
00472
00473 memcpy (xbuf, data, 64);
00474 X = xbuf;
00475 }
00476 }
00477 #endif
00478 #if BYTE_ORDER == 0
00479 else
00480 #endif
00481 #if BYTE_ORDER >= 0
00482 {
00483
00484
00485
00486
00487 const md5_byte_t *xp = data;
00488 int i;
00489
00490 # if BYTE_ORDER == 0
00491 X = xbuf;
00492 # else
00493 # define xbuf X
00494 # endif
00495 for (i = 0; i < 16; ++i, xp += 4)
00496 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
00497 }
00498 #endif
00499 }
00500
00501 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00502
00503
00504
00505
00506 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00507 #define SET(a, b, c, d, k, s, Ti)\
00508 t = a + F (b,c,d) + X[k] + Ti;\
00509 a = ROTATE_LEFT (t, s) + b
00510
00511 SET (a, b, c, d, 0, 7, T1);
00512 SET (d, a, b, c, 1, 12, T2);
00513 SET (c, d, a, b, 2, 17, T3);
00514 SET (b, c, d, a, 3, 22, T4);
00515 SET (a, b, c, d, 4, 7, T5);
00516 SET (d, a, b, c, 5, 12, T6);
00517 SET (c, d, a, b, 6, 17, T7);
00518 SET (b, c, d, a, 7, 22, T8);
00519 SET (a, b, c, d, 8, 7, T9);
00520 SET (d, a, b, c, 9, 12, T10);
00521 SET (c, d, a, b, 10, 17, T11);
00522 SET (b, c, d, a, 11, 22, T12);
00523 SET (a, b, c, d, 12, 7, T13);
00524 SET (d, a, b, c, 13, 12, T14);
00525 SET (c, d, a, b, 14, 17, T15);
00526 SET (b, c, d, a, 15, 22, T16);
00527 #undef SET
00528
00529
00530
00531
00532 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00533 #define SET(a, b, c, d, k, s, Ti)\
00534 t = a + G (b,c,d) + X[k] + Ti;\
00535 a = ROTATE_LEFT (t, s) + b
00536
00537 SET (a, b, c, d, 1, 5, T17);
00538 SET (d, a, b, c, 6, 9, T18);
00539 SET (c, d, a, b, 11, 14, T19);
00540 SET (b, c, d, a, 0, 20, T20);
00541 SET (a, b, c, d, 5, 5, T21);
00542 SET (d, a, b, c, 10, 9, T22);
00543 SET (c, d, a, b, 15, 14, T23);
00544 SET (b, c, d, a, 4, 20, T24);
00545 SET (a, b, c, d, 9, 5, T25);
00546 SET (d, a, b, c, 14, 9, T26);
00547 SET (c, d, a, b, 3, 14, T27);
00548 SET (b, c, d, a, 8, 20, T28);
00549 SET (a, b, c, d, 13, 5, T29);
00550 SET (d, a, b, c, 2, 9, T30);
00551 SET (c, d, a, b, 7, 14, T31);
00552 SET (b, c, d, a, 12, 20, T32);
00553 #undef SET
00554
00555
00556
00557
00558 #define H(x, y, z) ((x) ^ (y) ^ (z))
00559 #define SET(a, b, c, d, k, s, Ti)\
00560 t = a + H (b,c,d) + X[k] + Ti;\
00561 a = ROTATE_LEFT (t, s) + b
00562
00563 SET (a, b, c, d, 5, 4, T33);
00564 SET (d, a, b, c, 8, 11, T34);
00565 SET (c, d, a, b, 11, 16, T35);
00566 SET (b, c, d, a, 14, 23, T36);
00567 SET (a, b, c, d, 1, 4, T37);
00568 SET (d, a, b, c, 4, 11, T38);
00569 SET (c, d, a, b, 7, 16, T39);
00570 SET (b, c, d, a, 10, 23, T40);
00571 SET (a, b, c, d, 13, 4, T41);
00572 SET (d, a, b, c, 0, 11, T42);
00573 SET (c, d, a, b, 3, 16, T43);
00574 SET (b, c, d, a, 6, 23, T44);
00575 SET (a, b, c, d, 9, 4, T45);
00576 SET (d, a, b, c, 12, 11, T46);
00577 SET (c, d, a, b, 15, 16, T47);
00578 SET (b, c, d, a, 2, 23, T48);
00579 #undef SET
00580
00581
00582
00583
00584 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00585 #define SET(a, b, c, d, k, s, Ti)\
00586 t = a + I (b,c,d) + X[k] + Ti;\
00587 a = ROTATE_LEFT (t, s) + b
00588
00589 SET (a, b, c, d, 0, 6, T49);
00590 SET (d, a, b, c, 7, 10, T50);
00591 SET (c, d, a, b, 14, 15, T51);
00592 SET (b, c, d, a, 5, 21, T52);
00593 SET (a, b, c, d, 12, 6, T53);
00594 SET (d, a, b, c, 3, 10, T54);
00595 SET (c, d, a, b, 10, 15, T55);
00596 SET (b, c, d, a, 1, 21, T56);
00597 SET (a, b, c, d, 8, 6, T57);
00598 SET (d, a, b, c, 15, 10, T58);
00599 SET (c, d, a, b, 6, 15, T59);
00600 SET (b, c, d, a, 13, 21, T60);
00601 SET (a, b, c, d, 4, 6, T61);
00602 SET (d, a, b, c, 11, 10, T62);
00603 SET (c, d, a, b, 2, 15, T63);
00604 SET (b, c, d, a, 9, 21, T64);
00605 #undef SET
00606
00607
00608
00609
00610 pms->abcd[0] += a;
00611 pms->abcd[1] += b;
00612 pms->abcd[2] += c;
00613 pms->abcd[3] += d;
00614 }
00615
00616 static void
00617 md5_init (md5_state_t *pms)
00618 {
00619 pms->count[0] = pms->count[1] = 0;
00620 pms->abcd[0] = 0x67452301;
00621 pms->abcd[1] = T_MASK ^ 0x10325476;
00622 pms->abcd[2] = T_MASK ^ 0x67452301;
00623 pms->abcd[3] = 0x10325476;
00624 }
00625
00626 static void
00627 md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes)
00628 {
00629 const md5_byte_t *p = data;
00630 int left = nbytes;
00631 int offset = (pms->count[0] >> 3) & 63;
00632 md5_word_t nbits = (md5_word_t)(nbytes << 3);
00633
00634 if (nbytes <= 0)
00635 return;
00636
00637
00638 pms->count[1] += nbytes >> 29;
00639 pms->count[0] += nbits;
00640 if (pms->count[0] < nbits)
00641 pms->count[1]++;
00642
00643
00644 if (offset) {
00645 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00646
00647 memcpy (pms->buf + offset, p, copy);
00648 if (offset + copy < 64)
00649 return;
00650 p += copy;
00651 left -= copy;
00652 md5_process (pms, pms->buf);
00653 }
00654
00655
00656 for (; left >= 64; p += 64, left -= 64)
00657 md5_process (pms, p);
00658
00659
00660 if (left)
00661 memcpy (pms->buf, p, left);
00662 }
00663
00664 static void
00665 md5_finish (md5_state_t *pms, md5_byte_t digest[16])
00666 {
00667 static const md5_byte_t pad[64] = {
00668 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00669 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00670 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00671 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00672 };
00673 md5_byte_t data[8];
00674 int i;
00675
00676
00677 for (i = 0; i < 8; ++i)
00678 data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
00679
00680 md5_append (pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
00681
00682 md5_append (pms, data, 8);
00683 for (i = 0; i < 16; ++i)
00684 digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
00685 }