/*
  base64.c

  base64 routines borrowed from lynx, which borrowed them from rpem.

  Original public domain code by Mark Riordan <riordanmr@clvax1.cl.msu.edu>.
  
  Dug Song <dugsong@monkey.org>
  
  $Id: base64.c,v 1.2 1999/12/17 18:37:00 dugsong Exp $
*/

#include <sys/types.h>

#define MAX_BASE64_VAL	63
#define DEC(c)		pr2six[(int)c]
  
static u_char pr2six[256];

static char six2pr[64] = {
  'A','B','C','D','E','F','G','H','I','J','K','L','M',
  'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  'a','b','c','d','e','f','g','h','i','j','k','l','m',
  'n','o','p','q','r','s','t','u','v','w','x','y','z',
  '0','1','2','3','4','5','6','7','8','9','+','/'
};

int
base64_decode(char *in, char *out, int len)
{
  static int first = 1;
  int j, inlen, outlen;
  char *enc = in, *txt = out;

  /* If this is the first call, initialize the mapping table. */
  if (first) {
    first = 0;
    for (j = 0; j < 256; j++)
      pr2six[j] = MAX_BASE64_VAL + 1;
    for (j = 0; j < 64; j++)
      pr2six[(int)six2pr[j]] = j;
  }
  /* Strip leading whitespace. */
  while (*in==' ' || *in == '\t') in++;

  /*
    Figure out how many characters are in the input buffer.
    If this would decode into more bytes than would fit into
    the output buffer, adjust the number of input bytes downwards.
  */
  for (enc = in; pr2six[(int)*enc] <= MAX_BASE64_VAL; enc++) ;
  inlen = enc - in - 1;
  if ((outlen = ((inlen + 3) / 4) * 3) > len)
    inlen = (len * 4) / 3;
  
  for (enc = in; inlen > 0; enc += 4, inlen -= 4) {
    *(txt++) = DEC(*enc) << 2 | DEC(enc[1]) >> 4;
    *(txt++) = DEC(enc[1]) << 4 | DEC(enc[2]) >> 2;
    *(txt++) = DEC(enc[2]) << 6 | DEC(enc[3]);
  }
  if (inlen & 03) {
    if (pr2six[(int)enc[-2]] > MAX_BASE64_VAL)
      outlen -= 2;
    else
      outlen -= 1;
  }
  return(outlen);
}
