/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
#include "base64.h"
char base64_table[] = {
  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  "abcdefghijklmnopqrstuvwxyz"
  "0123456789+/"
};

#define decode(c) if(c >= 'A' && c <= 'Z') c  = c - 'A'; \
             else if(c >= 'a' && c <= 'z') c  = c - 'a' + 26; \
             else if(c >= '0' && c <= '9') c  = c - '0' + 52; \
             else if(c == '+')             c  = 62; \
             else if(c == '/')             c  = 63; \
             else                          c  = 0; \

int base64_encode(char **dst, const char *src, unsigned int len) {
  unsigned int x, y = 0;
  unsigned int n = 3;
  char triple[3];
  char quad[4];

  char *ptr = NULL, *ptr_tmp = NULL;
  
  for(x = 0; x < len; x += 3) {
    if((len - x) / 3 == 0)
      n = (len - x) % 3;
    memset(triple, 0, 3 * sizeof(char));
    memcpy(triple, &src[x], n * sizeof(char));

    quad[0] = base64_table[(triple[0] & 0xFC) >> 2];
    quad[1] = base64_table[((triple[0] & 0x03) << 4) | ((triple[1] & 0xF0) >> 4)];
    quad[2] = base64_table[((triple[1] & 0x0F) << 2) | ((triple[2] & 0xC0) >> 6)];
    quad[3] = base64_table[triple[2] & 0x3F];

    if(n < 3)
      quad[3] = '=';
    if(n < 2)
      quad[2] = '=';
    
    ptr_tmp = (char *)realloc(ptr, (y + 5) * sizeof(char));
    if (ptr_tmp != NULL)
      ptr = ptr_tmp;
    else
      return 0;

    memcpy(&ptr[y], quad, 4 * sizeof(char));
    ptr[y + 4] = '\0';
    y += 4;
  }
  *dst = ptr;
  
  return y;
}

int base64_decode(char **dst, const char *src, unsigned int len) {
  unsigned int x, y = 0;
  char triple[3];
  char quad[4];

  char *ptr = NULL, *ptr_tmp = NULL;
  
  len = strlen(src);
  
  for(x = 0; x < len; x += 4) {
    memset(quad, 0, 4 * sizeof(char));
    memcpy(quad, &src[x], (4 - (len - x) % 4) * sizeof(char));

    decode(quad[0]);
    decode(quad[1]);
    decode(quad[2]);
    decode(quad[3]);
    
    triple[0] = ((quad[0] << 2) & 0xFC) | ((quad[1] >> 4) & 0x0F);
    triple[1] = ((quad[1] << 4) & 0xF0) | ((quad[2] >> 2) & 0x3F);
    triple[2] = ((quad[2] << 6) & 0xC0) | (quad[3] & 0xFF);

    ptr_tmp = (char *)realloc(ptr, (y + 4) * sizeof(char));
    if (ptr_tmp != NULL)
      ptr = ptr_tmp;
    else
      return 0;

    memcpy(&ptr[y], triple, 3 * sizeof(char));
    ptr[y + 3] = '\0';
    y += 3;      
  }
  *dst = ptr;

  return y;
}


syntax highlighted by Code2HTML, v. 0.9.1