XMMS2
src/xmms/bindata.c
Go to the documentation of this file.
00001 /*  XMMS2 - X Music Multiplexer System
00002  *  Copyright (C) 2003-2011 XMMS2 Team
00003  *
00004  *  PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2.1 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
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 "xmms/xmms_bindata.h"
00032 
00033 #include "xmmspriv/xmms_ringbuf.h"
00034 #include "xmmspriv/xmms_ipc.h"
00035 #include "xmmspriv/xmms_playlist.h"
00036 #include "xmmspriv/xmms_config.h"
00037 #include "xmmspriv/xmms_bindata.h"
00038 #include "xmmspriv/xmms_utils.h"
00039 
00040 struct xmms_bindata_St {
00041     xmms_object_t obj;
00042     const gchar *bindir;
00043 };
00044 
00045 static xmms_bindata_t *global_bindata;
00046 
00047 static void xmms_bindata_destroy (xmms_object_t *obj);
00048 
00049 typedef unsigned char md5_byte_t; /* 8-bit byte */
00050 typedef unsigned int md5_word_t; /* 32-bit word */
00051 
00052 /* Define the state of the MD5 Algorithm. */
00053 typedef struct md5_state_s {
00054     md5_word_t count[2]; /* message length in bits, lsw first */
00055     md5_word_t abcd[4];  /* digest buffer */
00056     md5_byte_t buf[64];  /* accumulate block */
00057 } md5_state_t;
00058 
00059 /* Initialize the algorithm. */
00060 static void md5_init (md5_state_t *pms);
00061 static void md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes);
00062 static void md5_finish (md5_state_t *pms, md5_byte_t digest[16]);
00063 
00064 static gchar *xmms_bindata_build_path (xmms_bindata_t *bindata, const gchar *hash);
00065 
00066 static gchar *xmms_bindata_client_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err);
00067 static xmmsv_t *xmms_bindata_client_retrieve (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *err);
00068 static void xmms_bindata_client_remove (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *);
00069 static GList *xmms_bindata_client_list (xmms_bindata_t *bindata, xmms_error_t *err);
00070 static gboolean _xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err);
00071 
00072 #include "bindata_ipc.c"
00073 
00074 xmms_bindata_t *
00075 xmms_bindata_init ()
00076 {
00077     gchar *tmp;
00078     xmms_bindata_t *obj;
00079     xmms_config_property_t *cv;
00080 
00081     obj = xmms_object_new (xmms_bindata_t, xmms_bindata_destroy);
00082 
00083     xmms_bindata_register_ipc_commands (XMMS_OBJECT (obj));
00084 
00085     tmp = XMMS_BUILD_PATH ("bindata");
00086     cv = xmms_config_property_register ("bindata.path", tmp, NULL, NULL);
00087     g_free (tmp);
00088 
00089     obj->bindir = xmms_config_property_get_string (cv);
00090 
00091     if (!g_file_test (obj->bindir, G_FILE_TEST_IS_DIR)) {
00092         if (g_mkdir_with_parents (obj->bindir, 0755) == -1) {
00093             xmms_log_error ("Couldn't create bindir %s", obj->bindir);
00094         }
00095     }
00096 
00097     global_bindata = obj;
00098 
00099     return obj;
00100 }
00101 
00102 static void
00103 xmms_bindata_destroy (xmms_object_t *obj)
00104 {
00105     xmms_bindata_unregister_ipc_commands ();
00106 }
00107 
00108 gchar *
00109 xmms_bindata_calculate_md5 (const guchar *data, gsize size, gchar ret[33])
00110 {
00111     md5_state_t state;
00112     md5_byte_t digest[16];
00113     int di;
00114     static gchar hex[] = {
00115         '0', '1', '2', '3', '4', '5', '6', '7',
00116         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
00117     };
00118 
00119     md5_init (&state);
00120     md5_append (&state, (const md5_byte_t *)data, size);
00121     md5_finish (&state, digest);
00122 
00123     for (di = 0; di < 16; ++di) {
00124         ret[di * 2] = hex[digest[di] >> 4];
00125         ret[di * 2 + 1] = hex[digest[di] & 0x0f];
00126     }
00127     ret[32] = 0;
00128     return ret;
00129 }
00130 
00131 static gchar *
00132 xmms_bindata_build_path (xmms_bindata_t *bindata, const gchar *hash)
00133 {
00134     return g_build_path (G_DIR_SEPARATOR_S, bindata->bindir, hash, NULL);
00135 }
00136 
00137 /** Add binary data from a plugin */
00138 gboolean
00139 xmms_bindata_plugin_add (const guchar *data, gsize size, gchar hash[33])
00140 {
00141     xmms_error_t err;
00142     return _xmms_bindata_add (global_bindata, data, size, hash, &err);
00143 }
00144 
00145 static gboolean
00146 _xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err)
00147 {
00148     const guchar *ptr;
00149     gsize left;
00150     gchar *path;
00151     FILE *fp;
00152 
00153     xmms_bindata_calculate_md5 (data, len, hash);
00154 
00155     path = xmms_bindata_build_path (bindata, hash);
00156 
00157     if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
00158         XMMS_DBG ("file %s is already in bindata dir", hash);
00159         g_free (path);
00160         return TRUE;
00161     }
00162 
00163     XMMS_DBG ("Creating %s", path);
00164     fp = fopen (path, "wb");
00165     if (!fp) {
00166         xmms_log_error ("Couldn't create %s", path);
00167         xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't create file on server!");
00168         g_free (path);
00169         return FALSE;
00170     }
00171 
00172     /* write the data to the file */
00173     ptr = data;
00174     left = len;
00175 
00176     while (left > 0) {
00177         size_t w;
00178 
00179         w = fwrite (ptr, 1, left, fp);
00180         if (!w && ferror (fp)) {
00181             fclose (fp);
00182             unlink (path);
00183 
00184             xmms_log_error ("Couldn't write data");
00185             xmms_error_set (err, XMMS_ERROR_GENERIC,
00186                             "Couldn't write data!");
00187             g_free (path);
00188             return FALSE;
00189         }
00190 
00191         left -= w;
00192         ptr += w;
00193     }
00194 
00195     fclose (fp);
00196     g_free (path);
00197 
00198     return TRUE;
00199 }
00200 
00201 char *
00202 xmms_bindata_client_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err)
00203 {
00204     gchar hash[33];
00205     if (_xmms_bindata_add (bindata, (guchar *)data->str, data->len, hash, err))
00206         return g_strdup (hash);
00207     return NULL;
00208 }
00209 
00210 static xmmsv_t *
00211 xmms_bindata_client_retrieve (xmms_bindata_t *bindata, const gchar *hash,
00212                               xmms_error_t *err)
00213 {
00214     xmmsv_t *res;
00215     gchar *path;
00216     GString *str;
00217     FILE *fp;
00218 
00219     path = xmms_bindata_build_path (bindata, hash);
00220 
00221     fp = fopen (path, "rb");
00222     if (!fp) {
00223         xmms_log_error ("Requesting '%s' which is not on the server", hash);
00224         xmms_error_set (err, XMMS_ERROR_NOENT, "File not found!");
00225         g_free (path);
00226         return NULL;
00227     }
00228 
00229     g_free (path);
00230 
00231     str = g_string_new (NULL);
00232     while (!feof (fp)) {
00233         gchar buf[1024];
00234         gint l;
00235 
00236         l = fread (buf, 1, 1024, fp);
00237         if (ferror (fp)) {
00238             g_string_free (str, TRUE);
00239             xmms_log_error ("Error reading bindata '%s'", hash);
00240             xmms_error_set (err, XMMS_ERROR_GENERIC, "Error reading file");
00241             fclose (fp);
00242             return NULL;
00243         }
00244         g_string_append_len (str, buf, l);
00245     }
00246 
00247     fclose (fp);
00248 
00249     res = xmmsv_new_bin ((unsigned char *)str->str, str->len);
00250 
00251     g_string_free (str, TRUE);
00252 
00253     return res;
00254 }
00255 
00256 static void
00257 xmms_bindata_client_remove (xmms_bindata_t *bindata, const gchar *hash,
00258                             xmms_error_t *err)
00259 {
00260     gchar *path;
00261     path = xmms_bindata_build_path (bindata, hash);
00262     if (unlink (path) == -1) {
00263         xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't remove file");
00264     }
00265     g_free (path);
00266     return;
00267 }
00268 
00269 static GList *
00270 xmms_bindata_client_list (xmms_bindata_t *bindata, xmms_error_t *err)
00271 {
00272     GList *entries = NULL;
00273     gchar *path;
00274     const gchar *file;
00275     GDir *dir;
00276 
00277     path = xmms_bindata_build_path (bindata, NULL);
00278     dir = g_dir_open (path, 0, NULL);
00279     g_free (path);
00280 
00281     if (!dir) {
00282         xmms_error_set (err, XMMS_ERROR_GENERIC,
00283                         "Couldn't open bindata directory");
00284         return NULL;
00285     }
00286 
00287     while ((file = g_dir_read_name (dir))) {
00288         entries = g_list_prepend (entries, xmmsv_new_string (file));
00289     }
00290 
00291     g_dir_close (dir);
00292 
00293     return entries;
00294 }
00295 
00296 /*
00297   Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
00298 
00299   This software is provided 'as-is', without any express or implied
00300   warranty.  In no event will the authors be held liable for any damages
00301   arising from the use of this software.
00302 
00303   Permission is granted to anyone to use this software for any purpose,
00304   including commercial applications, and to alter it and redistribute it
00305   freely, subject to the following restrictions:
00306 
00307   1. The origin of this software must not be misrepresented; you must not
00308      claim that you wrote the original software. If you use this software
00309      in a product, an acknowledgment in the product documentation would be
00310      appreciated but is not required.
00311   2. Altered source versions must be plainly marked as such, and must not be
00312      misrepresented as being the original software.
00313   3. This notice may not be removed or altered from any source distribution.
00314 
00315   L. Peter Deutsch
00316   ghost@aladdin.com
00317 
00318  */
00319 /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
00320 /*
00321   Independent implementation of MD5 (RFC 1321).
00322 
00323   This code implements the MD5 Algorithm defined in RFC 1321, whose
00324   text is available at
00325     http://www.ietf.org/rfc/rfc1321.txt
00326   The code is derived from the text of the RFC, including the test suite
00327   (section A.5) but excluding the rest of Appendix A.  It does not include
00328   any code or documentation that is identified in the RFC as being
00329   copyrighted.
00330 
00331   The original and principal author of md5.c is L. Peter Deutsch
00332   <ghost@aladdin.com>.  Other authors are noted in the change history
00333   that follows (in reverse chronological order):
00334 
00335   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
00336     either statically or dynamically; added missing #include <string.h>
00337     in library.
00338   2002-03-11 lpd Corrected argument list for main(), and added int return
00339     type, in test program and T value program.
00340   2002-02-21 lpd Added missing #include <stdio.h> in test program.
00341   2000-07-03 lpd Patched to eliminate warnings about "constant is
00342     unsigned in ANSI C, signed in traditional"; made test program
00343     self-checking.
00344   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
00345   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
00346   1999-05-03 lpd Original version.
00347  */
00348 
00349 /*
00350  * This package supports both compile-time and run-time determination of CPU
00351  * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
00352  * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
00353  * defined as non-zero, the code will be compiled to run only on big-endian
00354  * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
00355  * run on either big- or little-endian CPUs, but will run slightly less
00356  * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
00357  */
00358 
00359 #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
00360 #ifdef ARCH_IS_BIG_ENDIAN
00361 #  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
00362 #else
00363 #  define BYTE_ORDER 0
00364 #endif
00365 
00366 #define T_MASK ((md5_word_t)~0)
00367 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
00368 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
00369 #define T3    0x242070db
00370 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
00371 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
00372 #define T6    0x4787c62a
00373 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
00374 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
00375 #define T9    0x698098d8
00376 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
00377 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
00378 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
00379 #define T13    0x6b901122
00380 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
00381 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
00382 #define T16    0x49b40821
00383 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
00384 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
00385 #define T19    0x265e5a51
00386 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
00387 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
00388 #define T22    0x02441453
00389 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
00390 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
00391 #define T25    0x21e1cde6
00392 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
00393 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
00394 #define T28    0x455a14ed
00395 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
00396 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
00397 #define T31    0x676f02d9
00398 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
00399 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
00400 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
00401 #define T35    0x6d9d6122
00402 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
00403 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
00404 #define T38    0x4bdecfa9
00405 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
00406 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
00407 #define T41    0x289b7ec6
00408 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
00409 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
00410 #define T44    0x04881d05
00411 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
00412 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
00413 #define T47    0x1fa27cf8
00414 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
00415 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
00416 #define T50    0x432aff97
00417 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
00418 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
00419 #define T53    0x655b59c3
00420 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
00421 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
00422 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
00423 #define T57    0x6fa87e4f
00424 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
00425 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
00426 #define T60    0x4e0811a1
00427 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
00428 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
00429 #define T63    0x2ad7d2bb
00430 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
00431 
00432 
00433 static void
00434 md5_process (md5_state_t *pms, const md5_byte_t *data /*[64]*/)
00435 {
00436     md5_word_t
00437     a = pms->abcd[0], b = pms->abcd[1],
00438     c = pms->abcd[2], d = pms->abcd[3];
00439     md5_word_t t;
00440 #if BYTE_ORDER > 0
00441     /* Define storage only for big-endian CPUs. */
00442     md5_word_t X[16];
00443 #else
00444     /* Define storage for little-endian or both types of CPUs. */
00445     md5_word_t xbuf[16];
00446     const md5_word_t *X;
00447 #endif
00448 
00449     {
00450 #if BYTE_ORDER == 0
00451     /*
00452      * Determine dynamically whether this is a big-endian or
00453      * little-endian machine, since we can use a more efficient
00454      * algorithm on the latter.
00455      */
00456     static const int w = 1;
00457 
00458     if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
00459 #endif
00460 #if BYTE_ORDER <= 0 /* little-endian */
00461     {
00462         /*
00463          * On little-endian machines, we can process properly aligned
00464          * data without copying it.
00465          */
00466         if (!((data - (const md5_byte_t *)0) & 3)) {
00467             /* data are properly aligned */
00468             X = (const md5_word_t *)data;
00469         } else {
00470             /* not aligned */
00471             memcpy (xbuf, data, 64);
00472             X = xbuf;
00473         }
00474     }
00475 #endif
00476 #if BYTE_ORDER == 0
00477     else /* dynamic big-endian */
00478 #endif
00479 #if BYTE_ORDER >= 0 /* big-endian */
00480     {
00481         /*
00482          * On big-endian machines, we must arrange the bytes in the
00483          * right order.
00484          */
00485         const md5_byte_t *xp = data;
00486         int i;
00487 
00488 #  if BYTE_ORDER == 0
00489         X = xbuf;/* (dynamic only) */
00490 #  else
00491 #    define xbuf X /* (static only) */
00492 #  endif
00493         for (i = 0; i < 16; ++i, xp += 4)
00494         xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
00495     }
00496 #endif
00497     }
00498 
00499 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00500 
00501     /* Round 1. */
00502     /* Let [abcd k s i] denote the operation
00503        a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
00504 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00505 #define SET(a, b, c, d, k, s, Ti)\
00506   t = a + F (b,c,d) + X[k] + Ti;\
00507   a = ROTATE_LEFT (t, s) + b
00508     /* Do the following 16 operations. */
00509     SET (a, b, c, d,  0,  7,  T1);
00510     SET (d, a, b, c,  1, 12,  T2);
00511     SET (c, d, a, b,  2, 17,  T3);
00512     SET (b, c, d, a,  3, 22,  T4);
00513     SET (a, b, c, d,  4,  7,  T5);
00514     SET (d, a, b, c,  5, 12,  T6);
00515     SET (c, d, a, b,  6, 17,  T7);
00516     SET (b, c, d, a,  7, 22,  T8);
00517     SET (a, b, c, d,  8,  7,  T9);
00518     SET (d, a, b, c,  9, 12, T10);
00519     SET (c, d, a, b, 10, 17, T11);
00520     SET (b, c, d, a, 11, 22, T12);
00521     SET (a, b, c, d, 12,  7, T13);
00522     SET (d, a, b, c, 13, 12, T14);
00523     SET (c, d, a, b, 14, 17, T15);
00524     SET (b, c, d, a, 15, 22, T16);
00525 #undef SET
00526 
00527     /* Round 2. */
00528     /* Let [abcd k s i] denote the operation
00529        a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
00530 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00531 #define SET(a, b, c, d, k, s, Ti)\
00532   t = a + G (b,c,d) + X[k] + Ti;\
00533   a = ROTATE_LEFT (t, s) + b
00534      /* Do the following 16 operations. */
00535     SET (a, b, c, d,  1,  5, T17);
00536     SET (d, a, b, c,  6,  9, T18);
00537     SET (c, d, a, b, 11, 14, T19);
00538     SET (b, c, d, a,  0, 20, T20);
00539     SET (a, b, c, d,  5,  5, T21);
00540     SET (d, a, b, c, 10,  9, T22);
00541     SET (c, d, a, b, 15, 14, T23);
00542     SET (b, c, d, a,  4, 20, T24);
00543     SET (a, b, c, d,  9,  5, T25);
00544     SET (d, a, b, c, 14,  9, T26);
00545     SET (c, d, a, b,  3, 14, T27);
00546     SET (b, c, d, a,  8, 20, T28);
00547     SET (a, b, c, d, 13,  5, T29);
00548     SET (d, a, b, c,  2,  9, T30);
00549     SET (c, d, a, b,  7, 14, T31);
00550     SET (b, c, d, a, 12, 20, T32);
00551 #undef SET
00552 
00553     /* Round 3. */
00554     /* Let [abcd k s t] denote the operation
00555        a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
00556 #define H(x, y, z) ((x) ^ (y) ^ (z))
00557 #define SET(a, b, c, d, k, s, Ti)\
00558   t = a + H (b,c,d) + X[k] + Ti;\
00559   a = ROTATE_LEFT (t, s) + b
00560      /* Do the following 16 operations. */
00561     SET (a, b, c, d,  5,  4, T33);
00562     SET (d, a, b, c,  8, 11, T34);
00563     SET (c, d, a, b, 11, 16, T35);
00564     SET (b, c, d, a, 14, 23, T36);
00565     SET (a, b, c, d,  1,  4, T37);
00566     SET (d, a, b, c,  4, 11, T38);
00567     SET (c, d, a, b,  7, 16, T39);
00568     SET (b, c, d, a, 10, 23, T40);
00569     SET (a, b, c, d, 13,  4, T41);
00570     SET (d, a, b, c,  0, 11, T42);
00571     SET (c, d, a, b,  3, 16, T43);
00572     SET (b, c, d, a,  6, 23, T44);
00573     SET (a, b, c, d,  9,  4, T45);
00574     SET (d, a, b, c, 12, 11, T46);
00575     SET (c, d, a, b, 15, 16, T47);
00576     SET (b, c, d, a,  2, 23, T48);
00577 #undef SET
00578 
00579     /* Round 4. */
00580     /* Let [abcd k s t] denote the operation
00581        a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
00582 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00583 #define SET(a, b, c, d, k, s, Ti)\
00584   t = a + I (b,c,d) + X[k] + Ti;\
00585   a = ROTATE_LEFT (t, s) + b
00586      /* Do the following 16 operations. */
00587     SET (a, b, c, d,  0,  6, T49);
00588     SET (d, a, b, c,  7, 10, T50);
00589     SET (c, d, a, b, 14, 15, T51);
00590     SET (b, c, d, a,  5, 21, T52);
00591     SET (a, b, c, d, 12,  6, T53);
00592     SET (d, a, b, c,  3, 10, T54);
00593     SET (c, d, a, b, 10, 15, T55);
00594     SET (b, c, d, a,  1, 21, T56);
00595     SET (a, b, c, d,  8,  6, T57);
00596     SET (d, a, b, c, 15, 10, T58);
00597     SET (c, d, a, b,  6, 15, T59);
00598     SET (b, c, d, a, 13, 21, T60);
00599     SET (a, b, c, d,  4,  6, T61);
00600     SET (d, a, b, c, 11, 10, T62);
00601     SET (c, d, a, b,  2, 15, T63);
00602     SET (b, c, d, a,  9, 21, T64);
00603 #undef SET
00604 
00605     /* Then perform the following additions. (That is increment each
00606         of the four registers by the value it had before this block
00607         was started.) */
00608     pms->abcd[0] += a;
00609     pms->abcd[1] += b;
00610     pms->abcd[2] += c;
00611     pms->abcd[3] += d;
00612 }
00613 
00614 static void
00615 md5_init (md5_state_t *pms)
00616 {
00617     pms->count[0] = pms->count[1] = 0;
00618     pms->abcd[0] = 0x67452301;
00619     pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
00620     pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
00621     pms->abcd[3] = 0x10325476;
00622 }
00623 
00624 static void
00625 md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes)
00626 {
00627     const md5_byte_t *p = data;
00628     int left = nbytes;
00629     int offset = (pms->count[0] >> 3) & 63;
00630     md5_word_t nbits = (md5_word_t)(nbytes << 3);
00631 
00632     if (nbytes <= 0)
00633         return;
00634 
00635     /* Update the message length. */
00636     pms->count[1] += nbytes >> 29;
00637     pms->count[0] += nbits;
00638     if (pms->count[0] < nbits)
00639         pms->count[1]++;
00640 
00641     /* Process an initial partial block. */
00642     if (offset) {
00643         int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00644 
00645         memcpy (pms->buf + offset, p, copy);
00646         if (offset + copy < 64)
00647             return;
00648         p += copy;
00649         left -= copy;
00650         md5_process (pms, pms->buf);
00651     }
00652 
00653     /* Process full blocks. */
00654     for (; left >= 64; p += 64, left -= 64)
00655         md5_process (pms, p);
00656 
00657     /* Process a final partial block. */
00658     if (left)
00659         memcpy (pms->buf, p, left);
00660 }
00661 
00662 static void
00663 md5_finish (md5_state_t *pms, md5_byte_t digest[16])
00664 {
00665     static const md5_byte_t pad[64] = {
00666         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00667         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00668         0, 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     };
00671     md5_byte_t data[8];
00672     int i;
00673 
00674     /* Save the length before padding. */
00675     for (i = 0; i < 8; ++i)
00676         data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
00677     /* Pad to 56 bytes mod 64. */
00678     md5_append (pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
00679     /* Append the length. */
00680     md5_append (pms, data, 8);
00681     for (i = 0; i < 16; ++i)
00682         digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
00683 }