/**
 * Copyright (c) 2006, Opera Software ASA
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Opera Software ASA nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY OPERA SOFTWARE ASA AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL OPERA SOFTWARE ASA AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
http://en.wikipedia.org/wiki/Base64
http://en.wikipedia.org/wiki/UTF8

000000–00007F	
  0xxxxxxx	
  ASCII equivalence range; 
  byte begins with zero 
  seven x
000080–0007FF	
  110xxxxx 10xxxxxx	
  first byte begins with 110, the following byte begins with 10. 
  five x, six x
000800–00FFFF	
  1110xxxx 10xxxxxx 10xxxxxx	
  first byte begins with 1110, the following bytes begin with 10.
  four x, six x, six x
010000–10FFFF	
  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx	
  First byte begins with 11110, the following bytes begin with 10
  three x, six x, six x, six
*/

/**
 * Converts a string to base 64 encoding.
 * @param string The string that should be base 64 encoded
 * @returns A base 64 encoded string
 */
function convertStringToBase64(string)
{
  var out='', charCode=0, i=0, endBytes='', length=string.length;
  var puffer=[];
  var base64EncodeChars ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  while(charCode=string.charCodeAt(i++))
  {
    // convert to utf-8
    //000000–00007F	
    //0xxxxxxx
    if(charCode<0x80) 
    {
      puffer[puffer.length]=charCode;
    }
    //000080–0007FF	
    //110xxxxx 10xxxxxx
    else if(charCode<0x800)
    {
      puffer[puffer.length]=0xc0|(charCode>>6);
      puffer[puffer.length]=0x80|(charCode&0x3f);
    } 
    //000800–00FFFF	
    //1110xxxx 10xxxxxx 10xxxxxx
    else if(charCode<0x10000)
    {
      puffer[puffer.length]=0xe0|(charCode>>12);
      puffer[puffer.length]=0x80|((charCode>>6)&0x3f);
      puffer[puffer.length]=0x80|(charCode&0x3f);
    } 
    //010000–10FFFF	
    //11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    else
    {
      puffer[puffer.length]=0xf0|(charCode>>18);
      puffer[puffer.length]=0x80|((charCode>>12)&0x3f);
      puffer[puffer.length]=0x80|((charCode>>6)&0x3f);
      puffer[puffer.length]=0x80|(charCode&0x3f);
    } 
    if(i==length)
    {
      while(puffer.length%3) 
      {
        puffer[puffer.length]=0;
        endBytes+='=';
      }
    }
    if(puffer.length>2)
    {
      out+=base64EncodeChars[puffer[0]>>2];
      out+=base64EncodeChars[((puffer.shift()&3)<<4)|(puffer[0]>>4)];
      out+=base64EncodeChars[((puffer.shift()&0xf)<<2)|(puffer[0]>>6)];
      out+=base64EncodeChars[puffer.shift()&0x3f];
    }
  }
  return (out+endBytes);
}