function urlDecode(str){
    str=str.replace(new RegExp('\+','g'),' ');
    return unescape(str);
}
function urlEncode(str){
    str=escape(str);
    str=str.replace(new RegExp('\+','g'),'%2B');
    return str.replace(new RegExp('%20','g'),'+');
}


var END_OF_INPUT = -1;

	function base64_encode(s){
		b64arrays();
		return b64d2t(utf8t2d(s));
	}

	function base64_decode(s){
		b64arrays();
		return utf8d2t(b64t2d(s));
	}

	function b64_encode(s){
		b64arrays();
		return b64d2t(utf8t2d(s));
	}

	function b64_decode(s){
		b64arrays();
		return utf8d2t(b64t2d(s));
	}
	function encodeBase64(s){
		b64arrays();
		return b64d2t(utf8t2d(s));
	}

	function decodeBase64(s){
		b64arrays();
		return utf8d2t(b64t2d(s));
	}

	function utf8t2d(t)
		{
		t = t.replace(/\r\n/g,"\n");
		var d=new Array; var test=String.fromCharCode(237);
		if (test.charCodeAt(0) < 0)
			for(var n=0; n<t.length; n++)
				{
				var c=t.charCodeAt(n);
				if (c>0)
					d[d.length]= c;
				else {
					d[d.length]= (((256+c)>>6)|192);
					d[d.length]= (((256+c)&63)|128);}
				}
		else
			for(var n=0; n<t.length; n++)
				{
				var c=t.charCodeAt(n);
				// all the signs of asci => 1byte
				if (c<128)
					d[d.length]= c;
				// all the signs between 127 and 2047 => 2byte
				else if((c>127) && (c<2048)) {
					d[d.length]= ((c>>6)|192);
					d[d.length]= ((c&63)|128);}
				// all the signs between 2048 and 66536 => 3byte
				else {
					d[d.length]= ((c>>12)|224);
					d[d.length]= (((c>>6)&63)|128);
					d[d.length]= ((c&63)|128);}
				}
		return d;
		}

// returns plaintext from an array of bytesrepresenting dezimal numbers, which
// represent an UTF-8 encoded text; browser which does not understand unicode
// like NN401 will show "?"-signs instead
// expects an array of byterepresenting decimals; returns a string
	function utf8d2t(d)
		{
		var r=new Array; var i=0;
		while(i<d.length)
			{
			if (d[i]<128) {
				r[r.length]= String.fromCharCode(d[i]); i++;}
			else if((d[i]>191) && (d[i]<224)) {
				r[r.length]= String.fromCharCode(((d[i]&31)<<6) | (d[i+1]&63)); i+=2;}
			else {
				r[r.length]= String.fromCharCode(((d[i]&15)<<12) | ((d[i+1]&63)<<6) | (d[i+2]&63)); i+=3;}
			}
		return r.join("");
		}

// included in <body onload="b64arrays"> it creates two arrays which makes base64
// en- and decoding faster
// this speed is noticeable especially when coding larger texts (>5k or so)
	function b64arrays() {
	var b64s='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
		b64 = new Array();f64 =new Array();
		for (var i=0; i<b64s.length ;i++) {
			b64[i] = b64s.charAt(i);
			f64[b64s.charAt(i)] = i;
		}
	}

// creates a base64 encoded text out of an array of byerepresenting dezimals
// it is really base64 :) this makes serversided handling easier
// expects an array; returns a string
	function b64d2t(d) {
		var r=new Array; var i=0; var dl=d.length;
		// this is for the padding
		if ((dl%3) == 1) {
			d[d.length] = 0; d[d.length] = 0;}
		if ((dl%3) == 2)
			d[d.length] = 0;
		// from here conversion
		while (i<d.length)
			{
			r[r.length] = b64[d[i]>>2];
			r[r.length] = b64[((d[i]&3)<<4) | (d[i+1]>>4)];
			r[r.length] = b64[((d[i+1]&15)<<2) | (d[i+2]>>6)];
			r[r.length] = b64[d[i+2]&63];
			if ((i%57)==54)
				r[r.length] = "\n";
			i+=3;
			}
		// this is again for the padding
		if ((dl%3) == 1)
			r[r.length-1] = r[r.length-2] = "=";
		if ((dl%3) == 2)
			r[r.length-1] = "=";
		// we join the array to return a textstring
		var t=r.join("");
		return t;
		}

// returns array of byterepresenting numbers created of an base64 encoded text
// it is still the slowest function in this modul; I hope I can make it faster
// expects string; returns an array
	function b64t2d(t) {
		var d=new Array; var i=0;
		// here we fix this CRLF sequenz created by MS-OS; arrrgh!!!
		t=t.replace(/\n|\r/g,""); t=t.replace(/=/g,"");
		while (i<t.length)
			{
			d[d.length] = (f64[t.charAt(i)]<<2) | (f64[t.charAt(i+1)]>>4);
			d[d.length] = (((f64[t.charAt(i+1)]&15)<<4) | (f64[t.charAt(i+2)]>>2));
		  	d[d.length] = (((f64[t.charAt(i+2)]&3)<<6) | (f64[t.charAt(i+3)]));
		  	i+=4;
			}
		if (t.length%4 == 2)
			d = d.slice(0, d.length-2);
		if (t.length%4 == 3)
			d = d.slice(0, d.length-1);
		return d;
		}




var digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');




function toHex(n){
    var result = ''
    var start = true;
    for (var i=32; i>0;){
        i-=4;
        var digit = (n>>i) & 0xf;
        if (!start || digit != 0){
            start = false;
            result += digitArray[digit];
        }
    }
    return (result==''?'0':result);
}

function pad(str, len, pad){
    var result = str;
    for (var i=str.length; i<len; i++){
        result = pad + result;
    }
    return result;
}

function encodeHex(str){
    var result = "";
    for (var i=0; i<str.length; i++){
        result += pad(toHex(str.charCodeAt(i)&0xff),2,'0');
    }
    return result;
}

function decodeHex(str){
    str = str.replace(new RegExp("s/[^0-9a-zA-Z]//g"));
    var result = "";
    var nextchar = "";
    for (var i=0; i<str.length; i++){
        nextchar += str.charAt(i);
        if (nextchar.length == 2){
            result += ntos(eval('0x'+nextchar));
            nextchar = "";
        }
    }
    return result;

}

