/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Copyright (C) Paul Johnston 1999 - 2000.
 * Updated by Greg Holt 2000 - 2001.
 * Modified by Michel Chilowicz <michel@netastuces.org>
 * Under GPL License
 

*/ /*
 * Convert a 32-bit number to a hex string with ls-byte first
 */
var hex_chr = "0123456789abcdef";

function rhex(num)
{
  str = "";
  for(j = 0; j <= 3; j++)
    str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) +
           hex_chr.charAt((num >> (j * 8)) & 0x0F);
  return str;
} 

function int32toarray(int32)
{
  data = new Array();
  j=0;
  for (i=0;i<int32.length;i++)
  {
    for (k=0;k<4;k++) data[j++] = (int32[i]>>(8*k))&255;
  }
  return data;
}
    

/*
 * Convert a string to a sequence of 16-word blocks, stored as an array.
 * Append padding bits and the length, as described in the MD5 standard.
 */
function str2blks_MD5(str,type)
{
  nblk = ((str.length + 8) >> 6) + 1;
  blks = new Array(nblk * 16);
  for(i = 0; i < nblk * 16; i++) blks[i] = 0;
  if (type == 0)
  {
    for(i = 0; i < str.length; i++) blks[i >> 2] |= str[i] << ((i % 4) * 8);
  } else
  {
    for(i = 0; i < str.length; i++) blks[i >> 2] |= str.charCodeAt(i) << ((i % 4) * 8);
  }
  blks[i >> 2] |= 0x80 << ((i % 4) * 8);
  blks[nblk * 16 - 2] = str.length * 8;
  return blks;
} /*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
} /*
 * Bitwise rotate a 32-bit number to the left
 */
function rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
} /*
 * These functions implement the basic operation for each round of the
 * algorithm.
 */
function cmn(q, a, b, x, s, t)
{
  return add(rol(add(add(a, q), add(x, t)), s), b);
}
function ff(a, b, c, d, x, s, t)
{
  return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function gg(a, b, c, d, x, s, t)
{
  return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function hh(a, b, c, d, x, s, t)
{
  return cmn(b ^ c ^ d, a, b, x, s, t);
}
function ii(a, b, c, d, x, s, t)
{
  return cmn(c ^ (b | (~d)), a, b, x, s, t);
} /*
 * Take a string and return the hex representation of its MD5.
 */



function calcmd5(str,type)
{
  //Modified by MC
  //str = formatStringForMd5(str);
  x = str2blks_MD5(str,type);
  a =  1732584193;
  b = -271733879;
  c = -1732584194;
  d =  271733878;   for(i = 0; i < x.length; i += 16)
  {
    olda = a;
    oldb = b;
    oldc = c;
    oldd = d;     a = ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = ff(c, d, a, b, x[i+10], 17, -42063);
    b = ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = ff(d, a, b, c, x[i+13], 12, -40341101);
    c = ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = ff(b, c, d, a, x[i+15], 22,  1236535329);        a = gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = gg(c, d, a, b, x[i+11], 14,  643717713);
    b = gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = gg(c, d, a, b, x[i+15], 14, -660478335);
    b = gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = gg(b, c, d, a, x[i+12], 20, -1926607734);
   
    a = hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = hh(b, c, d, a, x[i+14], 23, -35309556);
    a = hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = hh(d, a, b, c, x[i+12], 11, -421815835);
    c = hh(c, d, a, b, x[i+15], 16,  530742520);
    b = hh(b, c, d, a, x[i+ 2], 23, -995338651);     a = ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = ii(c, d, a, b, x[i+10], 15, -1051523);
    b = ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = ii(d, a, b, c, x[i+15], 10, -30611744);
    c = ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = ii(b, c, d, a, x[i+ 9], 21, -343485551);     a = add(a, olda);
    b = add(b, oldb);
    c = add(c, oldc);
    d = add(d, oldd);
  }
  //return rhex(a) + rhex(b) + rhex(c) + rhex(d);
  int32 = new Array(a,b,c,d);
  return int32toarray(int32);
}

//Cryptor by Michel Chilowicz <michel@netastuces.org>
//Under GNU/GPL (cf http://www.gnu.org)

values64 = new Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
"P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
"p","q","r","s","t","u","v","w","x","y","z",
"0","1","2","3","4","5","6","7","8","9","+","/");

function base64_encode(tab)
{
  var resultat ="";
  for (i=0;i<tab.length+1;i+=3)
  {
    if (tab.length < (i+1)) //==i
    {
      return resultat;
    } else if (tab.length == (i+1))
    {
      resultat+=values64[tab[i] >> 2]+values64[(tab[i] << 4)&48]+"==";
      return resultat;
    } else if (tab.length == (i+2))
    {
      resultat+=values64[tab[i] >> 2]+values64[((tab[i] << 4)&48) | (tab[i+1] >> 4)]+values64[(tab[i+1] << 2)&60]+"=";
      return resultat;
    } else
    {
      resultat+=values64[tab[i] >> 2]+values64[((tab[i] << 4)&48) | (tab[i+1] >> 4)]+values64[((tab[i+1] << 2)&60) | (tab[i+2] >>6)]+values64[tab[i+2]&63];
    }
  }
}

function base64_filter(text)
{
  var resultat = "";
  for (i=0;i<text.length;i++)
  {
    var ordinal = text.charCodeAt(i);
    if (((ordinal>47) && (ordinal<58)) || ((ordinal>64) && (ordinal<91)) || ((ordinal>96) && (ordinal<123)) || (ordinal==43) || (ordinal==47) || (ordinal==61))
    {
      resultat+=text.substr(i,1);
    }
  }
  return resultat;
}

function let2num(let)
{
  var ordinal = let;
  if ((ordinal>47) && (ordinal<58)) return (ordinal +4);
  if ((ordinal>64) && (ordinal<91)) return (ordinal-65);
  if ((ordinal>96) && (ordinal<123)) return (ordinal-71);
  if (ordinal==43) return 62;
  if (ordinal==47) return 63;
  if (ordinal==61) return -1;
  return -1;
}


function base64_decode(text)
{
  var j=0;
  data = new Array();
  text = base64_filter(text);
  for (i=0;i<text.length;i+=4)
  {
    var car0 = let2num(text.charCodeAt(i)); 
    var car1 = let2num(text.charCodeAt(i+1)); 
    var car2 = let2num(text.charCodeAt(i+2));
    var car3 = let2num(text.charCodeAt(i+3));
    if ((car0 > -1) && (car1>-1)) data[j++] = (car0 << 2) | (car1 >> 4);
    if ((car1 > -1) && (car2>-1)) data[j++] = ((car1 & 15) << 4) | (car2 >> 2);
    if ((car2 > -1) && (car3>-1)) data[j++] = ((car2 & 3) << 6) | (car3);
  }
  return data;
}

function encode_text(text)
{
  var data = new Array();
  for (i=0;i<text.length;i++) data[i] = text.charCodeAt(i);
  return base64_encode(data);
}

function decode_text(text)
{
  var data = new Array();
  var resultat = '';
  data = base64_decode(text);
  for (i=0;i<data.length;i++) resultat+=String.fromCharCode(data[i]);
  return resultat;
}

function mc4(data,key)
{
  var tab1 = new Array();
  var tab2 = new Array();
  var resultat = new Array();
  for (i=0;i<256;i++)
  {
    tab1[i] = i;
    tab2[i] = key[i%(key.length)];
  }
  var j=0;
  for (var i=0;i<256;i++)
  {
    j= (j+ tab1[i] + tab2[j])%256;
    var temp = tab1[i];
    tab1[i] = tab1[j];
    tab1[j] = temp;
  }
  i=0;j=0;
  for (var k=0;k<data.length;k++)
  {
    i = (i+1)%256;
    j = (j+tab1[i])%256;
    var temp = tab1[i];
    tab1[i] = tab1[j];
    tab1[j] = temp;
    resultat[k] = data[k] ^ tab1[(tab1[i] + tab1[j])%256];
  }
  return resultat;
}

function octet_alea()
{
  return (Math.floor(Math.random()*256));
}

function crypt_text(text,password)
{
  var data = new Array();
  var key = new Array();
  var hash = new Array();
  
  //data[0] = 19;data[1] = 29;
  //key[0] = 17;key[1] = 25;
  //data = mc4(data,key);
  //data = mc4(data,key);
  //alert(data[1]);
  
  for (var i=0;i<8;i++) 
  {
    data[i] = 0;
    key[i] = octet_alea();
  }
  for (var j=0;j<text.length;j++) data[i+j] = text.charCodeAt(j);
  for (var j=0;j<password.length;j++) key[i+j] = password.charCodeAt(j);
  hash = calcmd5(key,0); 
  data = mc4(data,hash);
  for (var i=0;i<8;i++) data[i] = key[i];
  resultat = base64_encode(data);
  return resultat;
}

function decrypt_text(text,password)
{
  var data = new Array();
  var key = new Array();
  var hash = new Array();
  data = base64_decode(text);
  for (i=0;i<8;i++)
  {
    key[i] = data[i];
  }
  //data = data.slice(8,data.length);
  for (j=0;j<password.length;j++) key[i+j] = password.charCodeAt(j);
  hash = calcmd5(key,0);
  data = mc4(data,hash);
  var resultat = "";
  for (i=8;i<data.length;i++) resultat+=String.fromCharCode(data[i]);
  return resultat;
}

function encryptMD5(sToCrypt, acceptEmpty)
{
    var sRet = new Array();
    if(acceptEmpty == 0)
    {
        sRet = calcmd5(sToCrypt,1); 
    }
    return  sRet;    
}

//----------------------------------------------------------
//
//  encrypte le mot de passe une fois MD5 encode base 64
//
//----------------------------------------------------------
function encryptInput_MD5_and_Base64(id, acceptEmpty)
{
    var tabHash = new Array(); // tableau retourné par le HMD5
    var txtToHash = document.getElementById(id); // controle à poster...
    if(txtToHash != null) // ca serait mieux qu'il existe...
    {
       // si on accepte les chaines vides et que la chaine est vide... alors on ne fait rien
       if(acceptEmpty == 0 || txtToHash.value != '') 
       {
            var formatedString = formatStringForMd5(txtToHash.value);
            tabHash = calcmd5(formatedString, 1); // HMD5
            txtToHash.value = base64_encode(tabHash); // base 64
       }
    }
    
}

//----------------------------------------------------------
//
// 1/ encrypte le mot de passe une fois MD5 encode base 64
// 2/ xor avec un grain de sel qui existe le temps de l'identification
// 3/ Ré - encrypte le mot de passe une fois MD5 encode base 64 !!!
//----------------------------------------------------------
function encryptInput_MD5_and_Base64_WithSault(id, acceptEmpty, idSault)
{
    var toHash;
    var tabHash = new Array();
    var sRet = '';
    var txtToHash = document.getElementById(id);
    var txtSault = document.getElementById(idSault);
    var sSaultKey = '';
    if(txtToHash != null && txtSault != null && txtSault.value != '')
    {
       if(acceptEmpty == 0 || txtToHash.value != '')
       {
            // recup le grain de sel...
            sSaultKey = txtSault.value;

            // 1/ 1er encryption du mot de passe hashMD5 + encodage base 64
            var formatedString = formatStringForMd5(txtToHash.value);
            
            tabHash = calcmd5(formatedString, 1);
            sRet = base64_encode(tabHash);
            
            //alert("HMD5  base 64 : " + sRet);
            
            // 2/ xor du resultat...
            sRet = xor_str(sRet, sSaultKey);
            //alert("key : " + sSaultKey + " xor :" + sRet);
            //alert(" reverse ? out 2 x XOR : " + xor_str(sRet, sSaultKey));
            
            // 3/ 2eme encryption du mot de passe hashMD5 + encodage base 64
            tabHash = new Array();
            tabHash = calcmd5(sRet, 1);
            sRet = base64_encode(tabHash);
       }
       txtToHash.value = sRet;
    }
    
}

//----------------------------------------------------------
//
// applique un xor sur la chaine 
// sIn avec la clé sKey (longueur recalculé en modulo)...
// 
//----------------------------------------------------------
function xor_str(sIn, sKey)
{
    var sRet = "";
	if(sIn != null && sKey != null && sKey != "" && sKey != "undefined")
    {
        sRet = "";
	    for(i=0;i < sIn.length;++i)
	    {
	        var cKey = sKey.charCodeAt(i%sKey.length);
	        var cIn = sIn.charCodeAt(i);
	       // alert("cKey : " + String.fromCharCode(cKey) + " cIn : " + String.fromCharCode(cIn) + " xor : " + String.fromCharCode(cKey^cIn));
		    sRet = sRet + String.fromCharCode(cKey^cIn);
	    }
	}
	
	return sRet;
}

//----------------------------------------------------------
//
// Function used to transform a string so that it only contains
// letters which have an ASCII value between 0 and 256 (1 byte)
// 
//----------------------------------------------------------
function formatStringForMd5(str){
    var strResult = "";
    for(i = 0; i<str.length; i++)
    {
        if(str.charCodeAt(i)>255)
        {
            //The value of the letter can be represented in hexa by Oxabcd
            //This value only can be represented by two bytes
            //As we want one byte values, we will append two letters to the word
            //instead of one : the first one will have 0xcd as value and the second
            //will have 0xab as value
            var valCharPoidsFaible = str.charCodeAt(i)& 0x00FF;
            var valCharPoidsFort = str.charCodeAt(i)& 0xFF00;
            valCharPoidsFort = valCharPoidsFort>>8;
            
            //We now can append the two letters
            strResult+=String.fromCharCode(valCharPoidsFaible);
            strResult+=String.fromCharCode(valCharPoidsFort);
        }
        else
        {
            strResult+=str.charAt(i);
        }
    }
    return strResult;
}

//----------------------------------------------------------
//
// Function used to force lower case on a target content
// 
//----------------------------------------------------------
function forceLowerCaseOnTargetContent(sTargetId)
{
    var oTarget = document.getElementById(sTargetId);
    if(oTarget)
    {
        oTarget.value = oTarget.value.toLowerCase();
    }
    else
    {
        alert("Exception : Impossible to find target while applying Lower Case Treatement");
    }
}

//----------------------------------------------------------
//
// Function used to force Upper case on a target content
// 
//----------------------------------------------------------
function forceUpperCaseOnTargetContent(sTargetId)
{
    var oTarget = document.getElementById(sTargetId);
    if(oTarget)
    {
        oTarget.value = oTarget.value.toUpperCase();
    }
    else
    {
        alert("Exception : Impossible to find target while applying Lower Case Treatement");
    }
}