/* MD5 code */

function au(x, y)
{
  var l = (x & 65535) + (y & 65535);
  var h = (x >> 16) + (y >> 16) + (l >> 16);
  return (h << 16) | (l & 65535);
}

function rol(val, b)
{
  return (val << b) | (val >>> (32 - b));
}

function ff(a, b, c, d, x, s, t) {return au(rol(au(au(a, ((b & c) | ((~b) & d))), au(x, t)), s),b);}
function gg(a, b, c, d, x, s, t) {return au(rol(au(au(a, ((b & d) | (c & (~d)))), au(x, t)), s),b);}
function hh(a, b, c, d, x, s, t) {return au(rol(au(au(a, (b ^ c ^ d)), au(x, t)), s),b);}
function ii(a, b, c, d, x, s, t) {return au(rol(au(au(a, (c ^ (b | (~d)))), au(x, t)), s),b);}

function md5(s)
{
var i,j,k;
var ostt = new Array(4);
var stt = new Array(4);
var x = Array();

    for (i=0;i<s.length;i++) x[i>>2] |= s.charCodeAt(i) << i*8;
    var len = s.length*8;

    var bc = s.length*1;
    var wc = (bc - (bc % 4)) / 4;
    var bp = (bc % 4) * 8;
    
    var nw = (((bc + 8) - ((bc + 8) % 64)) / 64 + 1) * 16;

    x[wc] |= 0x80 << bp;
    x[nw-2] = bc << 3;
    x[nw-1] = bc >>> 29;
    
    stt[0] =  0x67452301; stt[1] =  0xefcdab89; stt[2] =  0x98badcfe; stt[3] =  0x10325476;
    sf = new Array(7,12,17,22);
    sg = new Array(5,9,14,20);
    sh = new Array(4,11,16,23);
    si = new Array(6,10,15,21);
    var ffa = new Array(0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,
                        0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
                        0x6b901122,0xfd987193,0xa679438e,0x49b40821);
    var gga = new Array(0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x2441453,
                        0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,
                        0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a);
    var hha = new Array(0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,
                        0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x4881d05,
                        0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665);
    var iia = new Array(0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
                        0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
                        0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391);
    
    for(i = 0; i < x.length; i += 16) {
        for (j=0;j<3;j++) ostt[j] = stt[j];
        for (j=0;j<4;j++) 
          for (k=0;k<4;k++) 
            stt[(4-k)%4] = ff(stt[(4-k)%4], stt[(4-k+1)%4], 
                              stt[(4-k+2)%4], stt[(4-k+3)%4], x[i+ j*4+k], sf[k] , ffa[j*4+k]);
        for (j=0;j<4;j++) 
          for (k=0;k<4;k++) 
            stt[(4-k)%4] = gg(stt[(4-k)%4], stt[(4-k+1)%4], 
                              stt[(4-k+2)%4], stt[(4-k+3)%4], x[i+ (1+j*4+k*5)%16], sg[k] , gga[j*4+k]);
        for (j=0;j<4;j++)  
          for (k=0;k<4;k++) 
            stt[(4-k)%4] = hh(stt[(4-k)%4], stt[(4-k+1)%4], 
                              stt[(4-k+2)%4], stt[(4-k+3)%4], x[i+ (5+j*12+k*3)%16], sh[k] , hha[j*4+k]);
        for (j=0;j<4;j++) 
          for (k=0;k<4;k++) 
            stt[(4-k)%4] = ii(stt[(4-k)%4], stt[(4-k+1)%4], 
                              stt[(4-k+2)%4], stt[(4-k+3)%4], x[i+ (j*12+k*7)%16], si[k] , iia[j*4+k]);
        for (j=0;j<3;j++) stt[j] = au(stt[j], ostt[j]);
    }
    var s = "";
    for (i = 0; i < 16; i++)
    {
        s += "0123456789ABCDEF".charAt((stt[i>>2] >> ((i%4)*8+4)) & 15) +
             "0123456789ABCDEF".charAt((stt[i>>2] >> ((i%4)*8  )) & 15);
    }
    return s;
}

/* End MD5 */