/*
** basic-encode v1.1.1
**
** Encode or decode http basic authentication string
**
** Copyright (C) 18.8.1998 by Andreas Ley <Andreas.Ley@rz.uni-karlsruhe.de>
**
** 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** This program has been tested on a HP9000/715 with HP-UX A.09.07
** In this environment, neither lint -u nor gcc -Wall -pedantic -fsyntax-only
** produce any messages. If you encounter any errors or need to make any
** changes to port it to another platform, please contact me.
**
** Version history
**
** Version 1.1.1 - 28.10.2005
**	Fixed umlauts (unsigned char)
**
** Version 1.1 - 10.11.1999
**	Added encoding functionality
**
** Version 1.0 - 18.8.1998
**	Initial version
*/

static char copyright[]="@(#)Copyright (C) 1998,1999,2005 by Andreas Ley (Andreas.Ley@rz.uni-karlsruhe.de)";
static char sccsid[]="@(#)basic-encode v1.1.1 - Encode or decode http basic authentication string";


#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifndef FALSE
#define	FALSE	(0)		/* This is the naked Truth */
#define	TRUE	(1)		/* and this is the Light */
#endif


char	*image;
int	debug=0,opt_decode=FALSE;

char encoding[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
char encoding[64]={
	65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,
	89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,
	114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,43,47
};
*/
char decoding[256];


static unsigned char *encode(text)
unsigned char	*text;
{
	unsigned char	*buffer,*ptr,*rptr;
	int		len,rlen;

	if (debug)
		(void)fprintf(stderr,"encode(\"%s\")\n",text);

	len=strlen((char *)text);
	rlen=((len+2)/3)*4;

	if (!(buffer=(unsigned char*)malloc((size_t)rlen+1))) {
		(void)fprintf(stderr,"%s: cannot malloc %d bytes: ",image,rlen+1);
		perror(NULL);
	}

	for (ptr=text,rptr=buffer;len>0;ptr+=3,len-=3) {
		*rptr++=encoding[ptr[0]>>2];
		*rptr++=encoding[(ptr[0]&0x03)<<4|(ptr[1]&0xf0)>>4];
		*rptr++=encoding[(ptr[1]&0x0f)<<2|(len>2?(ptr[2]&0xc0)>>6:0)];
		*rptr++=len>2?encoding[ptr[2]&0x3f]:'=';
	}

	*rptr='\0';
	return(buffer);
}



static unsigned char *decode(text)
unsigned char	*text;
{
	unsigned char	*buffer,*ptr,*rptr;
	int		len,rlen;

	if (debug)
		(void)fprintf(stderr,"decode(\"%s\")\n",text);

	for (len=0;decoding[text[len]]<=63;len++);
	rlen=((len+3)/4)*3;

	if (!(buffer=(unsigned char*)malloc((size_t)rlen+1))) {
		(void)fprintf(stderr,"%s: cannot malloc %d bytes: ",image,rlen+1);
		perror(NULL);
	}

	for (ptr=text,rptr=buffer;len>0;ptr+=4,len-=4) {
		if (len>1)
			*rptr++=decoding[ptr[0]]<<2|decoding[ptr[1]]>>4;
		if (len>2)
			*rptr++=decoding[ptr[1]]<<4|decoding[ptr[2]]>>2;
		if (len>3)
			*rptr++=decoding[ptr[2]]<<6|decoding[ptr[3]];
	}

	*rptr='\0';
	return(buffer);
}



static void usage()
{
	(void)fprintf(stderr,"Usage: %s [-e|-d] string [...]\n",image);
	(void)fprintf(stderr,"-e  encode string\n");
	(void)fprintf(stderr,"-d  decode string\n");
	exit(1);
}


int main(argc,argv)
int	argc;
char	*argv[];
{
	int		c;
	extern char	*optarg;
	extern int	optind;
	int		i;
	unsigned char	*result;

	if ((image=strrchr(argv[0],'/')))
		image++;
	else
		image=argv[0];
	if (strstr(image,"decode"))
		opt_decode=TRUE;

	while ((c=getopt(argc,argv,"Dedvh?"))!=EOF)
		switch ((char)c) {
		case 'D':
			debug++;
			break;
		case 'e':
			opt_decode=FALSE;
			break;
		case 'd':
			opt_decode=TRUE;
			break;
		case 'v':
			(void)fprintf(stderr,"%s\n",sccsid+4);
			(void)fprintf(stderr,"%s\n",copyright+4);
			exit(0);
		case 'h':
			(void)fprintf(stderr,"%s\n",sccsid+4);
			(void)fprintf(stderr,"%s\n",copyright+4);
		case '?':
			usage();
		}

	if (optind>=argc)
		usage();

	if (opt_decode) {
		for (i=0;i<256;i++)
			decoding[i]=64;
		for (i=0;i<64;i++)
			decoding[encoding[i]]=i;
	}

	for (;optind<argc;optind++) {
		result=opt_decode?decode((unsigned char*)argv[optind]):encode((unsigned char*)argv[optind]);
		(void)printf("%s\n",result);
		free(result);
	}

	return(0);
}

