var base64 = [
       '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

function charFromCharCode (charCode) {
    return unescape('%' + charCode.toString(16));
}

function reverseBase64 () {
  var r = new Object();
  for (var i = 0; i < 64; i++) {
    r[base64[i]] = i;
  } return r;
}

var reversedBase64 = reverseBase64();

function decode (encStr) {
    var charCodes = new Array();
    var decStr = "";

    /* charCodes contains the index values into the base64 array
       for each character in the encoded string */
    for (var i = 0; i < encStr.length; i++)
        charCodes[i] = reversedBase64[encStr.charAt(i)];

    for (var i = 0; i < encStr.length; i += 4) {
        /* bits24 is 4 groups of 6-bit character indexes */
        var bits24  = ( charCodes [i]     & 0xFF  ) <<  18;
            bits24 |= ( charCodes [i + 1] & 0xFF  ) <<  12;
            bits24 |= ( charCodes [i + 2] & 0xFF  ) <<   6;
            bits24 |= ( charCodes [i + 3] & 0xFF  ) <<   0;

        /* grab the character for the first 8 bits by masking off the
           last 16 bits and then shifting right */
        decStr     += charFromCharCode((bits24 & 0xFF0000) >> 16);

        /* if the next characer is a pad character, there won't be a
charCode
           for it; so charCodes[] will return false and the character
won't
           be decoded. */

        /* grab the character for the second 8 bits by masking off the
           last 8 bits and then shifting right */
        if (charCodes[i + 2])  // check for padding character =
            decStr += charFromCharCode((bits24 &   0xFF00) >>  8);

        /* grab the character for the last 8 bits */
        if (charCodes[i + 3])  // check for padding character =
            decStr += charFromCharCode((bits24 &     0xFF) >>  0);
   } return decStr;
}

function encode_base64_2003_old(Str) {
    var charCodes = new Array();
    var encStr = "";

    for (var i = 0; i < Str.length; i += 3) {
        /* grab groups of three characters, 24 bits, then split into
           4 groups of 6 bits, and use each group as an index into
           base64[] to get the encoded character */

        /* bits24 is 3 groups of 8-bit characters */
        var bits24  = ( Str.charCodeAt(i)     ) <<  16;

        if ( Str.substr(i + 1, i + 2) ) {
            bits24 |= ( Str.charCodeAt(i + 1) ) <<   8;
        }
        else {
            bits24 |= ( 0 )                     <<   8;
        }

        if ( Str.substr(i + 2, i + 3) ) {
            bits24 |= ( Str.charCodeAt(i + 2) ) <<   0;
        }
        else {
            bits24 |= ( 0 )                     <<   0;
        }

        encStr += base64[ (bits24 >>> 18) & 0x3F ];

        if ( (bits24 >>> 12) & 0x3F ) {
            encStr += base64[ (bits24 >>> 12) & 0x3F ];
        }
        else {
            encStr += '=';
        }

        if ( (bits24 >>> 6) & 0x3F ) {
            encStr += base64[ (bits24 >>>  6) & 0x3F ];
        }
        else {
            encStr += '=';
        }

        if ( (bits24 >>> 0) & 0x3F ) {
            encStr += base64[ (bits24 >>>  0) & 0x3F ];
        }
        else {
            encStr += '=';
        }
   } return encStr;
}

function encode_base64_2003_2(url,Str) {
    var charCodes = new Array();
    var encStr = "";
    var url_array = url.split("/");
    
       
    // if not found http in the Str
    // insert the host name
    if (Str.search('http') == -1)
       { 
       	// if Str's 1st char is /
       	if (Str.charAt(0) == '/')
   	   	   Str = url_array[0] + "//" + url_array[2] + Str;
       	else
       	   Str = url + Str;
        
        }
       
  
    for (var i = 0; i < Str.length; i += 3) {
        /* grab groups of three characters, 24 bits, then split into
           4 groups of 6 bits, and use each group as an index into
           base64[] to get the encoded character */

        /* bits24 is 3 groups of 8-bit characters */
        var bits24  = ( Str.charCodeAt(i)     ) <<  16;

        if ( Str.substr(i + 1, i + 2) ) {
            bits24 |= ( Str.charCodeAt(i + 1) ) <<   8;
        }
        else {
            bits24 |= ( 0 )                     <<   8;
        }

        if ( Str.substr(i + 2, i + 3) ) {
            bits24 |= ( Str.charCodeAt(i + 2) ) <<   0;
        }
        else {
            bits24 |= ( 0 )                     <<   0;
        }

        encStr += base64[ (bits24 >>> 18) & 0x3F ];

        if ( (bits24 >>> 12) & 0x3F ) {
            encStr += base64[ (bits24 >>> 12) & 0x3F ];
        }
        else {
            encStr += '=';
        }

        if ( (bits24 >>> 6) & 0x3F ) {
            encStr += base64[ (bits24 >>>  6) & 0x3F ];
        }
        else {
            encStr += '=';
        }

        if ( (bits24 >>> 0) & 0x3F ) {
            encStr += base64[ (bits24 >>>  0) & 0x3F ];
        }
        else {
            encStr += '=';
        }
   } return encStr;
}  
   
function encode_base64_2003(str) {
	var result = "";
	var i = 0;
	var sextet = 0;
	var leftovers = 0;
	var octet = 0;

	for (i=0; i < str.length; i++) {
		octet = str.charCodeAt(i);
		switch( i % 3 )
		{
			case 0:
			{
				sextet = ( octet & 0xFC ) >> 2 ;
				leftovers = octet & 0x03 ;

				// sextet contains first character in quadruple
				break;
			}

			case 1:
			{
				sextet = ( leftovers << 4 ) | ( ( octet & 0xF0 ) >> 4 );
				leftovers = octet & 0x0F ;

				// sextet contains 2nd character in quadruple
				break;
			}

			case 2:
			{
				sextet = ( leftovers << 2 ) | ( ( octet & 0xC0 ) >> 6 ) ;
				leftovers = ( octet & 0x3F ) ;

				// sextet contains third character in quadruple
				// leftovers contains fourth character in quadruple
				break;
			}
		}

		result = result + base64ToAscii(sextet);

		// don't forget about the fourth character if it is there
		if( (i % 3) == 2 )
		{
			result = result + base64ToAscii(leftovers);
		} 

	}

	// figure out what to do with leftovers and padding
	switch( str.length % 3 )
	{
		case 0:
		{
			// an even multiple of 3, nothing left to do
			break ;
		}
		case 1:
		{
			// one 6-bit chars plus 2 leftover bits
			leftovers =  leftovers << 4 ;
			result = result + base64ToAscii(leftovers);
			result = result + "==";
			break ;
		}
		case 2:
		{
			// two 6-bit chars plus 4 leftover bits
			leftovers = leftovers << 2 ;
			result = result + base64ToAscii(leftovers);
			result = result + "=";
			break ;
		}
	}

	return result;
}

function base64ToAscii(c)
{
	var theChar = 0;
	
	if (0 <= c && c <= 25)
	{
		theChar = String.fromCharCode(c + 65);
	}
	else if (26 <= c && c <= 51)
	{
		theChar = String.fromCharCode(c - 26 + 97);
	}
	else if (52 <= c && c <= 61)
	{
		theChar = String.fromCharCode(c - 52 + 48);
	}
	else if (c == 62)
	{
		theChar = '+';
	}
	else if( c == 63 )
	{
		theChar = '/';
	}
	else
	{
		theChar = String.fromCharCode(0xFF);
	}

	return theChar;
}
