byte* decode_base64(char* src,size_t ssize, size_t *ret_len)
{
  byte* outbuf;
  char* inb;
  int i;
  int l;
  int left;
  int pos;
  unsigned long triple;

  /* Exit on empty input */
  if (!ssize||src==NULL) {
    log_msg(LOG_LEVEL_DEBUG, "decode base64: empty string");
    return NULL;
  }

  /* exit on unpadded input */
  if (ssize % 4) {
    log_msg(LOG_LEVEL_WARNING, "decode_base64: '%s' has invalid length (missing padding characters?)", src);
    return NULL;
  }

  /* calculate length of decoded string, substract padding chars if any (ssize is >= 4) */
  size_t length = sizeof(byte) * ((ssize / 4) * 3)- (src[ssize-1] == '=') - (src[ssize-2] == '=');

  /* Initialize working pointers */
  inb = src;
  outbuf = (byte *)checked_malloc(length + 1);

  l = 0;
  triple = 0;
  pos=0;
  left = ssize;
  /*
   * Process entire inbuf.
   */
  while (left != 0)
    {
      left--;
      i = fromb64[(unsigned char)*inb];
      switch(i)
	{
	case FAIL:
	  log_msg(LOG_LEVEL_WARNING, "decode_base64: illegal character: '%c' in '%s'", *inb, src);
	  free(outbuf);
	  return NULL;
	  break;
	case SKIP:
	  break;
	default:
	  triple = triple<<6 | (0x3f & i);
	  l++;
	  break;
	}
      if (l == 4 || left == 0)
	{
	  switch(l)
	    {
	    case 2:
	      triple = triple>>4;
	      break;
	    case 3:
	      triple = triple>>2;
	      break;
	    default:
	      break;
	    }
	  for (l  -= 2; l >= 0; l--)
	    {
	      outbuf[pos]=( 0xff & (triple>>(l*8)));
	      pos++;
	    }
	  triple = 0;
	  l = 0;
	}
      inb++;
    }
  
  outbuf[pos]='\0';

  if (ret_len) *ret_len = pos;
  
  return outbuf;
}
byte* decode_base64(char* src,size_t ssize, size_t *ret_len)
{
  byte* outbuf;
  char* inb;
  int i;
  int l;
  int left;
  int pos;
  unsigned long triple;

   
  if (!ssize||src==NULL) {
    log_msg(LOG_LEVEL_DEBUG, "decode base64: empty string");
    return NULL;
  }

   
  if (ssize % 4) {
    log_msg(LOG_LEVEL_WARNING, "decode_base64: '%s' has invalid length (missing padding characters?)", src);
    return NULL;
  }

   
  size_t length = sizeof(byte) * ((ssize / 4) * 3)- (src[ssize-1] == '=') - (src[ssize-2] == '=');

   
  inb = src;
  outbuf = (byte *)checked_malloc(length + 1);

  l = 0;
  triple = 0;
  pos=0;
  left = ssize;
   
  while (left != 0)
    {
      left--;
      i = fromb64[(unsigned char)*inb];
      switch(i)
	{
	case FAIL:
	  log_msg(LOG_LEVEL_WARNING, "decode_base64: illegal character: '%c' in '%s'", *inb, src);
	  free(outbuf);
	  return NULL;
	  break;
	case SKIP:
	  break;
	default:
	  triple = triple<<6 | (0x3f & i);
	  l++;
	  break;
	}
      if (l == 4 || left == 0)
	{
	  switch(l)
	    {
	    case 2:
	      triple = triple>>4;
	      break;
	    case 3:
	      triple = triple>>2;
	      break;
	    default:
	      break;
	    }
	  for (l  -= 2; l >= 0; l--)
	    {
	      outbuf[pos]=( 0xff & (triple>>(l*8)));
	      pos++;
	    }
	  triple = 0;
	  l = 0;
	}
      inb++;
    }
  
  outbuf[pos]='\0';

  if (ret_len) *ret_len = pos;
  
  return outbuf;
}