#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>

#ifndef FALSE
#define FALSE 0
#define TRUE !FALSE
#endif
static char	vec[] =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
	
int decode_base64(char *buf, char *out);
int decode_uu(char *line, char *out);

int decode_rfc1522(char *in, char* out);
char *rfc1522s(char *in);
int encode_rfc1522(char *in, char* out);


int decode_base64(char *buf, char *out)
{
	int	i, num, len, j;
	int nout=0;
	long	d, val;
	char	nw[4], *p, *c;

	len = strlen(buf)-1;
	for (i = 0; i < len; i += 4)	{
		val = 0;
		num = 3;
		c = buf+i; 
		if (c[2] == '=')
			num = 1;
		else if (c[3] == '=') 
			num = 2;
		for (j = 0; j <= num; j++){
			if (!(p = strchr(vec, c[j]))) {
				return -1;
			}
			d = p-vec;
			d <<= (3-j)*6;
			val += d;
		}
		for (j = 2; j >= 0; j--){
			nw[j] = val & 255;
			val >>= 8;
		}
		memcpy(out+nout,nw,num);
		nout += num;
	}
	return nout;
}

#define DEC(c)	(((c) - ' ') & 077)

int decode_uu(char *line, char *out)
{
    int c, len;
    int nout=0;
    len = DEC(*line++);
    while (len) {
	if (*line==0) break;
        if (line[1]==0) break;
	c = DEC(*line) << 2 | DEC(line[1]) >> 4;
	out[nout++] = c;
	if (--len) {
	    if (line[2]==0) break;
	    c = DEC(line[1]) << 4 | DEC(line[2]) >> 2;
	    out[nout++] = c;
	    if (--len) {
	        if (line[3]==0) break;
		c = DEC(line[2]) << 6 | DEC(line[3]);
	        out[nout++] = c;
		len--;
	    }
	}
	line += 4;
    }
    return nout;
}


/* rfc1522 encoding / decoding routines */
    
 static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
                  "0123456789+/";

char *rfc1522s(char *in) {
	int n;
	static char rslt[2000];
	n = decode_rfc1522(in,rslt);
	return rslt;
}

/* decode a header in rfc1522 format */
int decode_rfc1522(char *in, char* out){
	char *pi, *po, *s1, *s2;
	int	 lww = TRUE;
	/*char WSPACE[] = " \t\n\r";*/
	char chset[80], chencode, c;
	int found = 0;

	for (pi=in, po=out; *pi!=0; pi++){
		c = *pi;
/*		if (!lww) {
			lww = (strchr(WSPACE,c)!=NULL);
			*po++ = c;
			continue;
		}else{
			lww = (strchr(WSPACE,c)!=NULL);
*/		{
			if (c != '='){ *po++ = *pi; continue;}
			if (pi[1] == 0){ *po++ = *pi; continue;}
			if (pi[1] != '?'){ *po++ = c; continue;}
			/* now find charset and encoding */
			for (s1=pi+2; *s1!=0; s1++) {
				if (*s1=='?') break;
			}
			if ((*s1!='?') ||(s1-pi+2)>70){ *po++ = *pi; continue;}
			ncpy(chset, pi+2, s1-pi+2);
			if (*s1++ == 0){ *po++ = *pi; continue;}
			if (*s1 == 0){ *po++ = *pi; continue;}
			chencode = *s1++;
			if (*s1++ != '?'){ *po++ = *pi; continue;}
			if ((s2 = strchr(s1,'?')) == NULL){ *po++ = *pi; continue;}
			*s2++ = 0; if (*s2 != '='){ *po++ = *pi; s2[-1] = '?'; continue;}
			lww = FALSE;
			found++;
			/* now decode it */
			
			if (chencode == 'B' || chencode == 'b'){
				int n;
				n=decode_base64(s1,po);
				/* n = sprintf(po,"B encoding(%s)",s1);*/
				pi = s2; po +=n;
			}else if (chencode == 'Q' || chencode=='q'){
				/* do Q decode */
				unsigned char *p,c1,c2;
				for (p=(unsigned char *)s1; *p; p++){
					if (*p=='_') *po++ = ' ';
					else if (*p=='='){
						c1 = p[1]; c2 = p[2];
						if (c1>='A') c1 = c1 - 'A' + 10; else c1 -= '0';
						if (c2>='A') c2 = c2 - 'A' + 10; else c2 -= '0';
						*po++ = c1 * 16 + c2;
						p += 2;
					} else
						*po++ = *p;
				}
				pi = s2;
			}else{
				imsg("Unknown encoding = %c\n", chencode);
				*po++ = *pi;
			}
			s2[-1] = '?'; /* restore input string we wrote 0 into */
		}
	}
	*po = 0;
	return found;
}

int ydecode(char *in,int insz,char *out) /* RL */
{
	int inpos,outpos;

	for(inpos=outpos=0;inpos<insz;) {
		if(*(in+inpos)=='\r' || *(in+inpos)=='\n') {inpos++; continue;}
		if(*(in+inpos)!='=') {
			*(out+outpos)=*(in+inpos)-42;
		} else {
			inpos++;
			*(out+outpos)=*(in+inpos)-106;
		}
		inpos++;
		outpos++;
	}
	return outpos;
}

char *decode_url(char *in) /* RL */
{
	int x,y;
	static char bf[400];
	char hex[3]={0};

	for (x=0,y=0;x<400&&x<strlen(in);x++,y++) {
		switch(in[x]) {
		case '+':
			bf[y] = ' ';
		break;

		case '%':
			strncpy(hex,&in[x+1],2);
			strlwr(hex);
			x+=2;

			if(((strcmp(hex,"26")==0)) || ((strcmp(hex,"3d")==0))) {
				bf[y]='%';
				y++;
				strcpy(bf,hex);
				y+=2;
				break;
			}

			bf[y]=(char)strtol(hex,NULL,16);
			break;

		default:
			bf[y]=in[x];
			break;
		}
	}
	in[x]='\0';
	return bf;
}