Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

thd_md5.c

Go to the documentation of this file.
00001 
00002 /**********************************************************************
00003  * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All    *
00004  * rights reserved.                                                   *
00005  *                                                                    *
00006  * License to copy and use this software is granted provided that it  *
00007  * is identified as the "RSA Data Security, Inc. MD5 Message-Digest   *
00008  * Algorithm" in all material mentioning or referencing this software *
00009  * or this function.                                                  *
00010  *                                                                    *
00011  * License is also granted to make and use derivative works provided  *
00012  * that such works are identified as "derived from the RSA Data       *
00013  * Security, Inc. MD5 Message-Digest Algorithm" in all material       *
00014  * mentioning or referencing the derived work.                        *
00015  *                                                                    *
00016  * RSA Data Security, Inc. makes no representations concerning either *
00017  * the merchantability of this software or the suitability of this    *
00018  * software for any particular purpose. It is provided "as is"        *
00019  * without express or implied warranty of any kind.                   *
00020  *                                                                    *
00021  * These notices must be retained in any copies of any part of this   *
00022  * documentation and/or software.                                     *
00023  **********************************************************************/
00024 
00025 /*======= Modified by RWCox for inclusion in the AFNI package ========*/
00026 /*------- These changes are released to the public domain     --------*/
00027 
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 
00032 #include <sys/utsname.h>  /* these 4 files are needed by the UNIQ_ */
00033 #include <sys/time.h>     /* functions at the bottom of this file  */
00034 #include <unistd.h>
00035 #include <ctype.h>
00036 
00037 typedef unsigned char *POINTER;   /* POINTER defines a generic pointer type */
00038 typedef unsigned short int UINT2; /* UINT2 defines a two byte word */
00039 typedef unsigned long int UINT4;  /* UINT4 defines a four byte word */
00040 
00041 /* MD5 context data type */
00042 
00043 typedef struct {
00044   UINT4 state[4];                                        /* state (ABCD) */
00045   UINT4 count[2];             /* number of bits, modulo 2^64 (lsb first) */
00046   unsigned char buffer[64];                              /* input buffer */
00047 } MD5_CTX;
00048 
00049 
00050 /* prototypes for some internal functions */
00051 
00052 static void MD5Init (MD5_CTX *);
00053 static void MD5Update (MD5_CTX *, unsigned char *, unsigned int);
00054 static void MD5Final (unsigned char [16], MD5_CTX *);
00055 
00056 static void MD5Transform (UINT4 [4], unsigned char [64]);
00057 static void Encode (unsigned char *, UINT4 *, unsigned int);
00058 static void Decode (UINT4 *, unsigned char *, unsigned int);
00059 
00060 /* Constants for MD5Transform routine.  */
00061 
00062 #define S11 7
00063 #define S12 12
00064 #define S13 17
00065 #define S14 22
00066 #define S21 5
00067 #define S22 9
00068 #define S23 14
00069 #define S24 20
00070 #define S31 4
00071 #define S32 11
00072 #define S33 16
00073 #define S34 23
00074 #define S41 6
00075 #define S42 10
00076 #define S43 15
00077 #define S44 21
00078 
00079 static unsigned char PADDING[64] = {
00080   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00081   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00082   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00083 };
00084 
00085 /* F, G, H and I are basic MD5 functions.  */
00086 
00087 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00088 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00089 #define H(x, y, z) ((x) ^ (y) ^ (z))
00090 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00091 
00092 /* ROTATE_LEFT rotates x left n bits.  */
00093 
00094 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00095 
00096 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00097    Rotation is separate from addition to prevent recomputation.  */
00098 
00099 #define FF(a, b, c, d, x, s, ac) { \
00100  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
00101  (a) = ROTATE_LEFT ((a), (s)); \
00102  (a) += (b); \
00103   }
00104 
00105 #define GG(a, b, c, d, x, s, ac) { \
00106  (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
00107  (a) = ROTATE_LEFT ((a), (s)); \
00108  (a) += (b); \
00109   }
00110 
00111 #define HH(a, b, c, d, x, s, ac) { \
00112  (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
00113  (a) = ROTATE_LEFT ((a), (s)); \
00114  (a) += (b); \
00115   }
00116 
00117 #define II(a, b, c, d, x, s, ac) { \
00118  (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
00119  (a) = ROTATE_LEFT ((a), (s)); \
00120  (a) += (b); \
00121   }
00122 
00123 /*----------------------------------------------------------------------
00124    MD5 initialization. Begins an MD5 operation, writing a new context.
00125 ------------------------------------------------------------------------*/
00126 
00127 static void MD5Init (MD5_CTX * context)
00128 {
00129   context->count[0] = context->count[1] = 0;
00130 
00131   /* Load magic initialization constants */
00132 
00133   context->state[0] = 0x67452301;
00134   context->state[1] = 0xefcdab89;
00135   context->state[2] = 0x98badcfe;
00136   context->state[3] = 0x10325476;
00137 }
00138 
00139 /*----------------------------------------------------------------------
00140    MD5 block update operation. Continues an MD5 message-digest
00141    operation, processing another message block, and updating the
00142    context.
00143 ------------------------------------------------------------------------*/
00144 
00145 static void MD5Update (MD5_CTX * context, unsigned char * input,
00146                                           unsigned int inputLen  )
00147 {
00148   unsigned int i, index, partLen;
00149 
00150   /* Compute number of bytes mod 64 */
00151 
00152   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
00153 
00154   /* Update number of bits */
00155 
00156   if( (context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3) )
00157     context->count[1]++;
00158 
00159   context->count[1] += ((UINT4)inputLen >> 29);
00160 
00161   partLen = 64 - index;
00162 
00163   /* Transform as many times as possible.  */
00164 
00165   if (inputLen >= partLen) {
00166 
00167    memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen);
00168 
00169    MD5Transform (context->state, context->buffer);
00170 
00171    for (i = partLen; i + 63 < inputLen; i += 64)
00172      MD5Transform (context->state, &input[i]);
00173 
00174    index = 0;
00175   }
00176   else
00177    i = 0;
00178 
00179   /* Buffer remaining input */
00180 
00181   memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i],
00182           inputLen-i);
00183 }
00184 
00185 /*----------------------------------------------------------------------
00186    MD5 finalization. Ends an MD5 message-digest operation, writing the
00187    the message digest and zeroizing the context.
00188 ------------------------------------------------------------------------*/
00189 
00190 static void MD5Final (unsigned char digest[16], MD5_CTX * context)
00191 {
00192   unsigned char bits[8];
00193   unsigned int index, padLen;
00194 
00195   /* Save number of bits */
00196 
00197   Encode (bits, context->count, 8);
00198 
00199   /* Pad out to 56 mod 64.  */
00200 
00201   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
00202   padLen = (index < 56) ? (56 - index) : (120 - index);
00203   MD5Update (context, PADDING, padLen);
00204 
00205   /* Append length (before padding) */
00206 
00207   MD5Update (context, bits, 8);
00208 
00209   /* Store state in digest */
00210 
00211   Encode (digest, context->state, 16);
00212 
00213   /* Zeroize sensitive information. */
00214 
00215   memset ((POINTER)context, 0, sizeof (*context));
00216 }
00217 
00218 /*----------------------------------------------------------------------
00219    MD5 basic transformation. Transforms state based on block.
00220 ------------------------------------------------------------------------*/
00221 
00222 static void MD5Transform (UINT4 state[4], unsigned char block[64])
00223 {
00224   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00225 
00226   Decode (x, block, 64);
00227 
00228   /* Round 1 */
00229 
00230   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00231   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00232   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00233   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00234   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00235   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00236   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00237   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00238   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00239   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00240   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00241   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00242   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00243   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00244   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00245   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00246 
00247   /* Round 2 */
00248 
00249   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00250   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00251   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00252   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00253   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00254   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00255   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00256   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00257   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00258   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00259   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00260   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00261   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00262   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00263   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00264   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00265 
00266   /* Round 3 */
00267 
00268   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00269   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00270   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00271   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00272   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00273   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00274   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00275   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00276   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00277   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00278   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00279   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00280   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00281   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00282   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00283   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00284 
00285   /* Round 4 */
00286 
00287   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00288   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00289   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00290   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00291   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00292   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00293   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00294   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00295   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00296   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00297   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00298   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00299   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00300   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00301   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00302   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00303 
00304   state[0] += a;
00305   state[1] += b;
00306   state[2] += c;
00307   state[3] += d;
00308 
00309   /* Zeroize sensitive information. */
00310 
00311   memset ((POINTER)x, 0, sizeof (x));
00312 }
00313 
00314 /*----------------------------------------------------------------------
00315    Encodes input (UINT4) into output (unsigned char). Assumes len is
00316    a multiple of 4.
00317 ------------------------------------------------------------------------*/
00318 
00319 static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
00320 {
00321   unsigned int i, j;
00322 
00323   for (i = 0, j = 0; j < len; i++, j += 4) {
00324     output[j] = (unsigned char)(input[i] & 0xff);
00325     output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
00326     output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
00327     output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
00328   }
00329 }
00330 
00331 /*----------------------------------------------------------------------
00332    Decodes input (unsigned char) into output (UINT4). Assumes len is
00333    a multiple of 4.
00334 ------------------------------------------------------------------------*/
00335 
00336 static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
00337 {
00338   unsigned int i, j;
00339 
00340   for (i = 0, j = 0; j < len; i++, j += 4)
00341     output[i] = ((UINT4)input[j])          | (((UINT4)input[j+1]) << 8) |
00342                (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24) ;
00343 }
00344 
00345 /*======================================================================
00346    The stuff below is some interface routines, by RWCox
00347 ========================================================================*/
00348 
00349 /*----------------------------------------------------------------------
00350   Function to print the 128 bit digest into a 32 character string
00351 ------------------------------------------------------------------------*/
00352 
00353 static char * MD5_static_printf( unsigned char digest[16] )
00354 {
00355   static char st[33] ;
00356 
00357   sprintf(st,
00358           "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ,
00359           digest[0] , digest[1] , digest[2] , digest[3] , digest[4] ,
00360           digest[5] , digest[6] , digest[7] , digest[8] , digest[9] ,
00361           digest[10], digest[11], digest[12], digest[13], digest[14],
00362           digest[15]
00363          ) ;
00364 
00365   return st ;
00366 }
00367 
00368 /*----------------------------------------------------------------------
00369   Digest an array and returns the printable string of the result
00370 ------------------------------------------------------------------------*/
00371 
00372 char * MD5_static_array( int n , char * bytes )
00373 {
00374    MD5_CTX context;
00375    unsigned char digest[16];
00376 
00377    if( n < 0 || bytes == NULL ) return NULL ;
00378 
00379    MD5Init( &context ) ;
00380    MD5Update( &context, bytes, n ) ;
00381    MD5Final( digest, &context ) ;
00382 
00383    return MD5_static_printf(digest) ;
00384 }
00385 
00386 char * MD5_malloc_array( int n , char * bytes )
00387 {
00388    char *st , *dy ;
00389    st = MD5_static_array( n , bytes ) ;
00390    if( st == NULL ) return NULL ;
00391    dy = (char *) malloc(33) ; strcpy(dy,st) ; return dy ;
00392 }
00393 
00394 /*----------------------------------------------------------------------*/
00395 
00396 char * MD5_static_string( char * string )
00397 {
00398    if( string == NULL ) return NULL ;
00399    return MD5_static_array( strlen(string) , string ) ;
00400 }
00401 
00402 char * MD5_malloc_string( char * string )
00403 {
00404    if( string == NULL ) return NULL ;
00405    return (char*)MD5_malloc_array( strlen(string) , string ) ;
00406 }
00407 
00408 /*----------------------------------------------------------------------*/
00409 /* Digests a file and prints the result.  */
00410 /*----------------------------------------------------------------------*/
00411 
00412 char * MD5_static_file(char * filename)
00413 {
00414   FILE *file;
00415   MD5_CTX context;
00416   int len;
00417   unsigned char buffer[1024] ;
00418   unsigned char digest[16] ;
00419 
00420   if( (file = fopen (filename, "rb")) == NULL ) return NULL ;
00421 
00422   MD5Init( &context ) ;
00423 
00424   while( len = fread(buffer, 1, 1024, file) )
00425       MD5Update( &context, buffer, len ) ;
00426 
00427   MD5Final( digest, &context );
00428   fclose (file);
00429 
00430   return MD5_static_printf( digest ) ;
00431 }
00432 
00433 char * MD5_malloc_file(char * filename)
00434 {
00435    char *st , *dy ;
00436 
00437    st = MD5_static_file( filename ) ;
00438    if( st == NULL ) return NULL ;
00439    dy = (char *) malloc(33) ; strcpy(dy,st) ; return dy ;
00440 }
00441 
00442 /*============================================================================*/
00443 
00444 /*----------------------------------------------------------------------------
00445    Return the output as a Base64 string, instead of a hex string
00446    -- strlen(result) is 22 instead of 32
00447    -- result is malloc()-ed and should be free()-d when appropriate
00448 ------------------------------------------------------------------------------*/
00449 
00450 extern void B64_to_base64( int, char *, int *, char ** ) ; /* in thd_base64.c */
00451 
00452 static char * MD5_to_B64( unsigned char digest[16] )
00453 {
00454    int nb64=0 ; char *b64=NULL ;
00455 
00456    B64_to_base64( 16 , (char *)digest , &nb64 , &b64 ) ;  /* thd_base64.c */
00457    if( nb64 <= 0 || b64 == NULL ) return NULL ;
00458    b64[nb64-3] = '\0' ;                           /* remove trailing "==" */
00459    return b64 ;
00460 }
00461 
00462 char * MD5_B64_array( int n , char * bytes )
00463 {
00464    MD5_CTX context;
00465    unsigned char digest[16];
00466 
00467    if( n < 0 || bytes == NULL ) return NULL ;
00468 
00469    MD5Init( &context ) ;
00470    MD5Update( &context, bytes, n ) ;
00471    MD5Final( digest, &context ) ;
00472 
00473    return MD5_to_B64( digest ) ;
00474 }
00475 
00476 char * MD5_B64_string( char * string )
00477 {
00478    if( string == NULL ) return NULL ;
00479    return MD5_B64_array( strlen(string) , string ) ;
00480 }
00481 
00482 char * MD5_B64_file(char * filename)
00483 {
00484   FILE *file;
00485   MD5_CTX context;
00486   int len;
00487   unsigned char buffer[1024] ;
00488   unsigned char digest[16] ;
00489 
00490   if( (file = fopen (filename, "rb")) == NULL ) return NULL ;
00491 
00492   MD5Init( &context ) ;
00493 
00494   while( len = fread(buffer, 1, 1024, file) )
00495       MD5Update( &context, buffer, len ) ;
00496 
00497   MD5Final( digest, &context );
00498   fclose (file);
00499 
00500   return MD5_to_B64( digest ) ;
00501 }
00502 
00503 /*-----------------------------------------------------------------------
00504   Return a globally unique identifier (I hope).  This is a malloc()-ed
00505   string of length <= 31 (plus the NUL byte; the whole thing will fit
00506   into a char[32] array).  The output does not contain any '/'s, so
00507   it could be used as a temporary filename.
00508   Method: generate a string from the system identfier information and
00509           the current time of day; MD5 hash this to a 128 byte code;
00510           Base64 encode this to a 22 byte string; replace '/' with '-'
00511           and '+' with '_'; add 4 character prefix (1st 3 characters
00512           of environment variable IDCODE_PREFIX plus '_').
00513   -- RWCox - 27 Sep 2001
00514 -------------------------------------------------------------------------*/
00515 
00516 char * UNIQ_idcode(void)
00517 {
00518    struct utsname ubuf ;
00519    struct timeval tv ;
00520    int    nn , ii ;
00521    int  nbuf ;
00522    char *buf , *idc , *eee ;
00523    static int ncall=0 ;                /* number of times I've been called */
00524 
00525    /* get info about this system */
00526 
00527    nn = uname( &ubuf ) ;               /* get info about this system */
00528    if( nn == -1 ){                     /* should never happen */
00529       strcpy( ubuf.nodename , "E" ) ;
00530       strcpy( ubuf.sysname  , "L" ) ;
00531       strcpy( ubuf.release  , "V" ) ;
00532       strcpy( ubuf.version  , "I" ) ;
00533       strcpy( ubuf.machine  , "S" ) ;
00534    }
00535 
00536    /* store system info into a string buffer */
00537 
00538    nbuf = strlen(ubuf.nodename)+strlen(ubuf.sysname)
00539          +strlen(ubuf.release )+strlen(ubuf.version)+strlen(ubuf.machine) ;
00540 
00541    buf = AFMALL(char, nbuf+64) ;      /* include some extra space */
00542    strcpy(buf,ubuf.nodename) ;
00543    strcat(buf,ubuf.sysname ) ;
00544    strcat(buf,ubuf.release ) ;
00545    strcat(buf,ubuf.version ) ;
00546    strcat(buf,ubuf.machine ) ;
00547 
00548    idc = AFMALL(char, 32) ;         /* will be output string */
00549 
00550    /* get time and store into buf */
00551 
00552    nn = gettimeofday( &tv , NULL ) ;
00553    if( nn == -1 ){              /* should never happen */
00554       tv.tv_sec  = (long) buf ;
00555       tv.tv_usec = (long) idc ;
00556    }
00557 
00558    sprintf(buf+nbuf,"%d%d%d%d",
00559           (int)tv.tv_sec,(int)tv.tv_usec,(int)getpid(),ncall) ;
00560    ncall++ ;
00561 
00562    /* get prefix for idcode from environment, if present */
00563 
00564    eee = getenv("IDCODE_PREFIX") ;
00565    if( eee != NULL && isalpha(eee[0]) ){
00566      for( ii=0 ; ii < 3 && isalnum(eee[ii]) ; ii++ )
00567        idc[ii] = eee[ii] ;
00568    } else {
00569      strcpy(idc,"NIH") ;
00570    }
00571    strcat(idc,"_") ;  /* recall idc was calloc()-ed */
00572 
00573    /* MD5+Base64 encode buf to be latter part of the idcode */
00574 
00575    eee = MD5_B64_string( buf ) ;
00576    if( eee != NULL ){                     /* should always work */
00577       int nn = strlen(eee) ;
00578       for( ii=0 ; ii < nn ; ii++ ){
00579               if( eee[ii] == '/' ) eee[ii] = '-' ;  /* / -> - */
00580          else if( eee[ii] == '+' ) eee[ii] = '_' ;  /* + -> _ */
00581       }
00582       strcat(idc,eee) ;
00583    } else {                               /* should never happen */
00584      nn = strlen(idc) ;
00585      sprintf(idc+nn,"%d_%d",(int)tv.tv_sec,(int)tv.tv_usec) ;
00586    }
00587 
00588    /* free workspaces and get outta here */
00589 
00590    if( eee != NULL ) free(eee) ;
00591    free(buf) ; return idc ;
00592 }
00593 
00594 /*----------------------------------------------------------------------
00595    Fill a user-supplied buffer (length at least 32) with an idcode
00596 ------------------------------------------------------------------------*/
00597 
00598 void UNIQ_idcode_fill( char *idc )
00599 {
00600    char *bbb ;
00601    if( idc == NULL ) return ;
00602    bbb = UNIQ_idcode() ;
00603    strcpy(idc,bbb) ; free(bbb) ; return ;
00604 }
00605 
00606 /*============================================================================*/
 

Powered by Plone

This site conforms to the following standards: