var constant = '_';
var 	alphabet	= new Array('A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , // 0 to 7
						'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , // 8 to 15
						'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , // 16 to 23
						'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , // 24 to 31
						'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , // 32 to 39
						'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , // 40 to 47
						'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , // 48 to 55
						'4' , '5' , '6' , '7' , '8' , '9' , '+' , '/' // 56 to 63
						);

var 	decodeTable	= new Array(-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , // 0 to 9
						-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , // 10 to 19
						-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , // 20 to 29
						-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , // 30 to 39
						-1 , -1 , -1 , 62 , -1 , -1 , -1 , 63 , 52 , 53 , // 40 to 49
						54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , -1 , -1 , // 50 to 59
						-1 , -1 , -1 , -1 , -1 , 0 , 1 , 2 , 3 , 4 , // 60 to 69
						5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , // 70 to 79
						15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , // 80 to 89
						25 , -1 , -1 , -1 , -1 , -1 , -1 , 26 , 27 , 28 , // 90 to 99
						29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , // 100 to 109
						39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , // 110 to 119
						49 , 50 , 51 // 120 to 122
						);


function encodeToString(s) {
	if (s== ""|| s == "undefined") return "";
	var encoded = encode(s);
	var encodedSB = new String();
	
	for (var i = 0; i < encoded.length; i++) {
		encodedSB += encoded [ i ];
	}
	return encodedSB;
}

function encode(bytes) {
	var sixbit;

	var output = new Array  ((parseInt((bytes.length - 1) / 3) + 1) * 4 );

	var outIndex = 0;
	var i = 0;
	
	while ((i + 3) <= bytes.length) {
		sixbit = (bytes.charCodeAt( i ) & 0xFC) >> 2;
		
		output [ outIndex++ ] = alphabet [ sixbit ];
		sixbit = ((bytes.charCodeAt( i ) & 0x3) << 4) + ((bytes.charCodeAt( i + 1 ) & 0xF0) >> 4);
					
		output [ outIndex++ ] = alphabet [ sixbit ];
		sixbit = ((bytes.charCodeAt( i + 1 ) & 0xF) << 2) + ((bytes.charCodeAt( i + 2 ) & 0xC0) >> 6);
					
		output [ outIndex++ ] = alphabet [ sixbit ];
		sixbit = bytes.charCodeAt( i + 2 ) & 0x3F;
					
		output [ outIndex++ ] = alphabet [ sixbit ];
		i += 3;
	}

	if (bytes.length - i == 2) {
		sixbit = (bytes.charCodeAt( i ) & 0xFC) >> 2;
		output [ outIndex++ ] = alphabet [ sixbit ];
		sixbit = ((bytes.charCodeAt( i ) & 0x3) << 4) + ((bytes.charCodeAt( i + 1 ) & 0xF0) >> 4);
		output [ outIndex++ ] = alphabet [ sixbit ];
		sixbit = (bytes.charCodeAt( i + 1 ) & 0xF) << 2;
		output [ outIndex++ ] = alphabet [ sixbit ];
		output [ outIndex++ ] = constant; //'=';
	} else if (bytes.length - i == 1) {
		sixbit = (bytes.charCodeAt( i ) & 0xFC) >> 2;
		output [ outIndex++ ] = alphabet [ sixbit ];
		sixbit = (bytes.charCodeAt( i ) & 0x3) << 4;
		output [ outIndex++ ] = alphabet [ sixbit ];
		output [ outIndex++ ] = constant; //'=';
		output [ outIndex++ ] = constant; //'=';
	}
	return output;
}

function  decodeToString(encoded) {
	if (encoded== ""|| encoded == "undefined") return "";
	
	var decoded = decode(encoded);
	var decodedSB = new String();
	var i=0;
	for (i = 0; i < decoded.length; i++) {
		decodedSB += (String.fromCharCode(decoded [ i ]));
	}
	return decodedSB;
}

function decode(encoded) {
	var decoded = null;
	var decodedLength = (parseInt(encoded.length / 4) * 3);
	var invalid = 0;

	if (encoded.length % 4 != 0) {
		//It isn't BASE64 encoded string
		return null;
	}
	if (encoded.charAt(encoded.length - 2) == constant/*'='*/) {
		invalid = 2;
	} else if (encoded.charAt(encoded.length - 1) == constant/*'='*/) {
		invalid = 1;
	}
	decodedLength -= invalid;
	decoded = new Array( decodedLength );

	var i = 0;
	var di = 0;
	var sixbit0;
	var  sixbit1;
	var sixbit2;
	var sixbit3;

	for (i = 0; i < encoded.length - 4; i += 4) {
		sixbit0 = decodeTable [ encoded.charCodeAt(i) ];
		sixbit1 = decodeTable [ encoded.charCodeAt(i + 1) ];
		sixbit2 = decodeTable [ encoded.charCodeAt(i + 2) ];
		sixbit3 = decodeTable [ encoded.charCodeAt(i + 3) ];

		decoded [ di++ ] = ((sixbit0 << 2) + ((sixbit1 & 0x30) >> 4));
		decoded [ di++ ] = (((sixbit1 & 0xF) << 4) + ((sixbit2 & 0x3C) >> 2));
		decoded [ di++ ] = (((sixbit2 & 0x3) << 6) + sixbit3);
	}

	switch (invalid) {
		case 0:
			sixbit0 = decodeTable [ encoded.charCodeAt(i) ];
			sixbit1 = decodeTable [ encoded.charCodeAt(i + 1) ];
			sixbit2 = decodeTable [ encoded.charCodeAt(i + 2) ];
			sixbit3 = decodeTable [ encoded.charCodeAt(i + 3) ];
			
			decoded [ di++ ] = ((sixbit0 << 2) + ((sixbit1 & 0x30) >> 4));
			decoded [ di++ ] = (((sixbit1 & 0xF) << 4) + ((sixbit2 & 0x3C) >> 2));
			decoded [ di++ ] = (((sixbit2 & 0x3) << 6) + sixbit3);
			break;

		case 1:
			sixbit0 = decodeTable [ encoded.charCodeAt(i) ];
			sixbit1 = decodeTable [ encoded.charCodeAt(i + 1) ];
			sixbit2 = decodeTable [ encoded.charCodeAt(i + 2) ];
			
			decoded [ di++ ] = ((sixbit0 << 2) + ((sixbit1 & 0x30) >> 4));
			decoded [ di++ ] = (((sixbit1 & 0xF) << 4) + ((sixbit2 & 0x3C) >> 2));
			
			break;

		case 2:
			sixbit0 = decodeTable [ encoded.charCodeAt(i) ];
			sixbit1 = decodeTable [ encoded.charCodeAt(i + 1) ];
	
			decoded [ di++ ] = ((sixbit0 << 2) + ((sixbit1 & 0x30) >> 4));
			break;
	}

	return decoded;
}
