// base64 js decoding routine, ascii only
// may, 2005 // by morgan
// base64 js encoding routine, inside win-1251 only
// may, 2005 // by morgan

var base64_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var base64_keys = [];
for ( var i=0; i<=64; i++) {
 base64_keys[base64_chars.charAt(i)] = i;
}

var b2c = [], c2b = [];
 function init_bc() {
  for (var i=0; i<128; i++) {
   b2c[i] = String.fromCharCode(i);
  }

  t = '€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ\xa0¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ';
  for ( i=128; i<256; i++) {
   b2c[i] = t.charAt(i-128);
  }

  for ( i=0; i<256; i++) {
   c2b[b2c[i]] = i;
  }
 }

function base64_encode( s) {
  init_bc();
  var j = s.length % 3;
  switch (j) {
   case 1: s += String.fromCharCode(0);
   case 2: s += String.fromCharCode(0);
  }

  var i = 0, n = s.length, rz = '';
  while (i < n) {
   k = c2b[s.charAt(i++)]<<16|c2b[s.charAt(i++)]<<8|c2b[s.charAt(i++)];
   rz += base64_chars.charAt(k>>18) + base64_chars.charAt(k>>12&0x3f) + base64_chars.charAt(k>>6&0x3f) + base64_chars.charAt(k&0x3f);
  }

  switch(j) {
   case 1: return (rz.substr(0,rz.length-2) + '==');
   case 2: return (rz.substr(0,rz.length-1) + '=');
  }

  return rz;
 } 

///////////////////////////////////

function base64_decode( s) {
 if ((s.length&3)||(!s.match(/^[a-z0-9+\/]+={0,2}$/i))) {
  return ''; // invalid input
 }

 var i = 0, rz = '', n = s.length;
 while (i < n) {
  k = base64_keys[s.charAt(i++)]<<18|
      base64_keys[s.charAt(i++)]<<12|
      base64_keys[s.charAt(i++)]<<6|
      base64_keys[s.charAt(i++)];

  rz += String.fromCharCode(k>>16,(k>>8)&0xff,k&0xff);
 }

 if ((i = s.indexOf('=')) != -1) {
  rz = rz.substr(0,rz.length-(n-i));
 }

 return rz;
}