#include "dfeed.h"

/* ------------------ library of stuff for web --------------------*/

void form_decode_mime(Chan *c,char *content);
static char *query_name[1000];
static char *query_val[1000];
static int nquery;
/* Query string */

void query_free(void)
{
	int i;
	for (i=0; i<nquery; i++) {
		free(query_name[i]);
		free(query_val[i]);
	}
	nquery = 0;
}

char *lib_encode(char *s)
{
   char *ss=s;
  for (;*s!=0;s++) {
    if (isspace(*s)) *s = '+';
  }
  return ss;
}
char *ref_encode(char *s)
{
	static char bf[BFSZ];
	ncpy(bf,s,BFSZ-1);
	lib_encode(bf);
	return bf;
}
char *towww(char *s)
{
  static char bf[BFSZ],*out;
  for (out=bf;*s!=0;s++) {
    	if (isspace(*s)) *s = '+';
  	if (*s=='+') {sprintf(out,"%%%x",*s); out += strlen(out);}
 	else if (*s=='&') {sprintf(out,"%%%x",*s); out += strlen(out);}
	else *out++ = *s;
  }
  *out++ = 0;
  return bf;
}

char *value_encode(char *s)
{
 	static char bf[2000];
	int i;
	char *out=bf;
	if (s==NULL) return "";
	for (i=0; i<2000 && *s!=0;i++,s++) {
	 	if (*s=='<') { strcpy(out,"&lt;"); out += strlen(out); }
		else if (*s=='>') { strcpy(out,"&gt;"); out += strlen(out); }
		else if (*s=='&') { strcpy(out,"&amp;"); out += strlen(out); }
		else if (*s=='"') { strcpy(out,"&#34;"); out += strlen(out); }
		else *out++ = *s;
	}
	*out++ = 0;
	return bf;
}
char hexbyte(char *s)
{
	char bf[3];
	int x;
	strncpy(bf,s,2);
	bf[2] = 0;
	sscanf(bf,"%x",&x);
	return (char) x;
}
char *decode_quote(char *s)
{
 	static char bf[2000];
	int i;
	char *out=bf;
	for (i=0; i<2000 && *s!=0;i++,s++) {
		if (*s<0) {
			*out++ = *s++;
			*out++ = *s;
		} else if (*s=='=') {
			if (s[1]==0) {*out++ = '\n'; continue;}
			*out++ = hexbyte(s+1);
			s+=2;
		} else *out++ = *s;
	}
	*out++ = 0;
	return bf;
}
char *text_encode(char *s)
{
 	static char bf[2000];
	int i;
	char *out=bf;
	for (i=0; i<2000 && *s!=0;i++,s++) {
		if (*s<0) {
			*out++ = *s++;
			*out++ = *s;
		} else if (*s=='<') { strcpy(out,"&lt;"); out += strlen(out); }
		else if (*s=='>') { strcpy(out,"&gt;"); out += strlen(out); }
		else if (*s=='&') { strcpy(out,"&amp;"); out += strlen(out); }
	 	else *out++ = *s;
	}
	*out++ = 0;
	return bf;
}
int get_read_wrap(void);
char *query_find(char *s)
{
 	int i;
	for (i=0; i<nquery; i++) if (strcmp(query_name[i],s)==0) return query_val[i];
	return "";
}
int query_show(void)
{
	int i;
	for (i=0; i<nquery; i++) {
		imsg("Query (%s) = (%s) \n",query_name[i],query_val[i]);
	}
	return TRUE;
}
int query_decode(char *q)
{
	char *cl;
	char bf[10000],val[2000],name[BFSZ];
	int x;

	query_free();
	if (q==NULL) return FALSE;
	strcpy(bf,q); cl = bf;
    	for(x=0;cl[0] != '\0';x++) {
    		getword(val,cl,'&');
    		plustospace(val);
        	unescape_url(val);
        	getword(name,val,'=');
		query_name[x] = strdup(name);
		query_val[x] = strdup(val);
    	}
	nquery = x;
        return TRUE;
}
void getword(char *word, char *line, char stop) 
{
    int x = 0,y;

    for(x=0;((line[x]) && (line[x] != stop));x++)
        word[x] = line[x];

    word[x] = '\0';
    if(line[x]) ++x;
    y=0;

    while(line[y++] = line[x++]);
}
char x2c(char *what) 
{
    register char digit;

    digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
    digit *= 16;
    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
    return(digit);
}

void unescape_url(char *url) 
{
    register int x,y;

    for(x=0,y=0;url[y];++x,++y) {
        if((url[x] = url[y]) == '%') {
            url[x] = x2c(&url[y+1]);
            y+=2;
        }
    }
    url[x] = '\0';
}

void plustospace(char *str) 
{
    register int x;

    for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
}


static char *form_name[1000];
static char *form_val[1000];
static int nform;
char *file_work(char *fname);
void cgi_addvar(char *name, char *value);
char *get_quote(char *s);
char *makeword(char *line, char stop) ;
char *fmakeword(FILE *f, char stop, int *cl);
void convert_crlf(char *s); /* turn crlf into lf's */

#ifdef WIN32
#define mktemp _mktemp
#endif
char *attach_fname(void)
{
	static char fname[BFSZ];
	char *s;
	static char bf[BFSZ];
	if (strlen(fname)!=0) return fname;
	strcpy(fname,"xxx");
	s = mktemp(fname);
	if (s==NULL) s = "attach.tmp";
	strcpy(bf,s);
	strcpy(fname,bf);
	return fname;
}
static char a_type[BFSZ],a_name[BFSZ];
char *attach_type(void)
{
	return a_type;
}
char *attach_name(void)
{
	return a_name;
}
/*
POST /scripts/test.exe HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, *x/x*
Accept-Language: en-us
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)
Host: orion:9999
Content-Length: 127
Connection: Keep-Alive

name=A+discussion+of&public=ON&T5=keywordshere&cmd_newgroup=Create%2FModify+discussion+group&description=Long+description+here.}
*/
int ispressed(char *s)
{
	char bf[BFSZ];
	if (strlen(form_find(s))>0) {
		return TRUE;
	}
	sprintf(bf,"%s.x",s);
	if (strlen(form_find(bf))>0) {
		return TRUE;
	}

	return FALSE;

}
void form_free(void)
{
	int i;
	for (i=0; i<nform; i++) {
		free(form_name[i]);
		free(form_val[i]);
	}
	nform = 0 ;
}
void form_decode(Chan *c)
{
	char *s;
	int n;
	int k;
	char content[BFSZ];
	char tmp[66000];
	ncpy(content,c->head->content_type,100);
	if (strstr(content,"multipart/form-data")!=NULL) {
		form_decode_mime(c,content);
		return;
	}

	chan_instart(c);
	for (s=tmp;TRUE;s++) {
		*s = chan_ingetc(c);
		if (*s==0) break;
		s[1] = 0;
		if (strstr(tmp,"\r\n\r\n")!=NULL) break;
	}	
	for (;TRUE;) {
		for(n=0;TRUE;) {
			k = chan_ingetc(c);
			if (k==0) break;
				if (k=='&') break;
			tmp[n++] = k;
		}
		if (n==0) return;
		tmp[n++] = 0;
		s = strchr(tmp,'\r'); if (s!=NULL) *s = 0;
		s = strchr(tmp,'\n'); if (s!=NULL) *s = 0;
		imsg("got word (%s)\n",tmp);	
	        plustospace(tmp);
	        unescape_url(tmp);
		s = strchr(tmp,'='); if (s==NULL) continue;
		*s = 0;
		form_name[nform] = strdup(tmp);
		form_val[nform] = strdup(s+1);
		imsg("Form (%s) = (%s) \n",form_name[nform],form_val[nform]);
		nform++;
	}
}
void form_decode_mime(Chan *c, char *content)
{	
	char bf[BFSZ];
	char bf2[BFSZ];
	char boundary[BFSZ];
	char bound_part[BFSZ];
	char bound_end[BFSZ];
	int cl;
	char name[BFSZ];
	char fname[BFSZ];
	char body[4000];
	char tmp[BFSZ];
	int inhead;
	int i,n;
	char lasteol = FALSE;
	FILE *attach;
	char *s = mygetenv("CONTENT_LENGTH");
	cl = atoi(s);
	strcpy(fname,"");
	attach = NULL;
	s = strstr(content,"boundary=");
	if (s==NULL) {
		emsg("Can't find boundary in mime contents %s",content);
		return;
	}
	s += 9;
	strcpy(boundary,get_quote(s));
	sprintf(bound_part,"--%s\r\n",boundary);
	sprintf(bound_end,"--%s--\r\n",boundary);
#ifdef FIX_STDOUT
	_setmode(_fileno(stdin),_O_BINARY);
#endif
	for (;(!feof(stdin)) && (cl>0);) {
		n = 0;
		for (i=0; (i<400) && (!feof(stdin)) && (cl>0); i++) {
			bf[i] = fgetc(stdin);
			cl--;
			n = i+1;
			if (bf[i]=='\n') break;

		}
		bf[n] = 0;
		imsg("Line length %d, %s",n,bf);
		if (strncmp(bf,bound_part,strlen(bound_part))==0) {
			inhead = TRUE;
			if (attach!=NULL) {
				fclose(attach);
				attach = NULL;
				sprintf(tmp,"%s\r\n",attach_fname()); 
				cgi_addvar(name,tmp);
				strcpy(fname,"");
			} else cgi_addvar(name,body);
		} else if (strncmp(bf,bound_end,strlen(bound_end))==0) {
			if (attach!=NULL) {
				fclose(attach);
				strcpy(fname,"");
				attach = NULL;
				sprintf(tmp,"%s\r\n",attach_fname()); 
				cgi_addvar(name,tmp);
				strcpy(fname,"");
			} else cgi_addvar(name,body);
			break;
		} else {
		 if (inhead) {
/*	Content-Disposition: form-data; name="reply" */
			imsg("Mime Headers %s",bf);
			if (strcmp(bf,"\r\n")==0) inhead = FALSE;
			if (isspace(bf[0])) goto skip;
			strcpy(bf2,bf); strlwr(bf2);
			if (strstr(bf2,"content-type: ")!=NULL) {
				s = bf + 14;
				ncpy(a_type,s,BFSZ-1);
				s = strchr(a_type,';'); if (s!=NULL) *s = 0;
				s = strchr(a_type,'\r'); if (s!=NULL) *s = 0;
				s = strchr(a_type,'\n'); if (s!=NULL) *s = 0;
			}
			if (strstr(bf2,"content-disposition:")!=NULL) {
skip:				s = strstr(bf,"name=");	if (s==NULL) continue;
				strcpy(name,get_quote(s+5));
				s = strstr(bf,"filename="); if (s==NULL) continue;
				strcpy(fname,get_quote(s+9));
				strcpy(a_name,fname);
				if (attach==NULL) attach = fopen(attach_fname(),"wb");
				lasteol = FALSE;
			}
			strlwr(bf);

		 } else {
			if (attach!=NULL) {
				if (lasteol) fwrite("\r\n",1,2,attach);
				lasteol = FALSE;
				if (n>2) if (strcmp(bf+n-2,"\r\n")==0) {
					n-=2;
					lasteol = TRUE;
				} 
				fwrite(bf,1,n,attach);
			} else if (strlen(name)>0) {
				if (strlen(body)>3000) continue;
				strcat(body,bf);
			}
		 }
		}
	}
	if (attach!=NULL) fclose(attach);
	attach = NULL;
	imsg("cl = %d\n",cl);
	
}
void cgi_addvar(char *name, char *value)
{
	char *s;
	if (strlen(name)==0) return;
	s = strdup(value);
	if (strlen(s)>1) s[strlen(s)-2] = 0;
	form_val[nform] = s;
	form_name[nform++] = strdup(name);
	/*imsg("Variable added (%s) = (%s) \n",name,s);*/
	strcpy(name,"");
	strcpy(value,"");
}
char *get_quote(char *s)
{
	static char bf[BFSZ];
	if (*s=='"') {
		ncpy(bf,s+1,BFSZ-1);
		s = strchr(bf,'"');
		if (s!=NULL) *s = 0;
	} else {
		ncpy(bf,s,BFSZ-1);
		s = strchr(bf,' ');if (s!=NULL) *s = 0;
		s = strchr(bf,';');if (s!=NULL) *s = 0;
		s = strchr(bf,'\n');if (s!=NULL) *s = 0;
	}
	return bf;
}
void form_get(void)
{
	int x,cl;
	char content[BFSZ];
	char *s = mygetenv("CONTENT_LENGTH");
	if (s==NULL) return;
	cl = atoi(s);

	strcpy(content,mygetenv("CONTENT_TYPE"));
	imsg("XForm content (%s)\n",content);
	if (strstr(content,"multipart/form-data")!=NULL) {
		//form_get_mime(content);
		return;
	}
	for(x=0;cl && (!feof(stdin));x++) {
	        form_val[x]= fmakeword(stdin,'&',&cl);
	        plustospace(form_val[x]);
	        unescape_url(form_val[x]);
	        form_name[x] = makeword(form_val[x],'=');
		convert_crlf(form_val[x]);
	}
	nform = x;
}
void convert_crlf(char *s)
{
	char *out=s;
	for (;*s!=0;s++) {
		if ((s[0] == '\r') && (s[1] == '\n')) s++;
		*out++ = *s;
	}
	*out++ = 0;
}
char *makeword(char *line, char stop) 
{
    int x = 0,y;
    char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));

    for(x=0;((line[x]) && (line[x] != stop));x++)
        word[x] = line[x];

    word[x] = '\0';
    if(line[x]) ++x;
    y=0;

    while(line[y++] = line[x++]);
    return word;
}

char *fmakeword(FILE *f, char stop, int *cl) 
{
    int wsize;
    char *word;
    int ll;

    wsize = 8024;
    ll=0;
    word = (char *) malloc(sizeof(char) * (wsize + 1));

    while(1) {
        word[ll] = (char)fgetc(f);
        if(ll==wsize) {
            word[ll+1] = '\0';
            wsize+=8024;
            word = (char *)realloc(word,sizeof(char)*(wsize+1));
        }
        --(*cl);
        if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
            if(word[ll] != stop) ll++;
            word[ll] = '\0';
            return word;
        }
        ++ll;
    }
}

int form_true(char *s)
{
	char bf[BFSZ];
	strcpy(bf,form_find(s));
	strlwr(bf);
	if (strstr(bf,"on")!=NULL) return TRUE;
	return FALSE;
}
int form_truei(char *s,int x)
{
	char bf[BFSZ];
	strcpy(bf,form_findi(s,x));
	strlwr(bf);
	if (strstr(bf,"on")!=NULL) return TRUE;
	return FALSE;
}
char *form_findi(char *s, int i)
{
	char bf[BFSZ];
	sprintf(bf,"%s_%d",s,i);
	return form_find(bf);
}
char *form_find(char *s)
{
 	int i;
/*	imsg("Form Find (%s) \n",s);*/
	for (i=0; i<nform; i++) {
		/*imsg("form_find [%d]  (%s) (%s) \n",i,s,form_name[i]);*/
		if (strcmp(form_name[i],s)==0) return form_val[i];
	}
	return query_find(s);
}
int form_n(void)
{
	return nform;
}
char *form_get_pair(int i, char *name, char *val)
{
	if (i>nform) return NULL;
	ncpy(name,form_name[i],BFSZ-1);
	ncpy(val,form_val[i],BFSZ-1);
	return name;
}
char *form_find_i(char *s, int i)
{
	char bf[BFSZ];
 	sprintf(bf,"%s%d",s,i); s = bf;
	for (i=0; i<nform; i++) if (strcmp(form_name[i],s)==0) return form_val[i];
	return "";
}

char *email_name(char *email)
{
	static char bf[BFSZ];
	char *s2;
	char *s;
	s = strchr(email,'(');
	if (s!=NULL) {
		ncpy(bf,s+1,BFSZ-1);
		s = strchr(bf,')');
		if (s!=NULL) *s = 0;
	}
	ncpy(bf,email,BFSZ-1);
	s = strchr(bf,'@');
	s2 = strchr(bf,' ');
	if (s==NULL) s = s2;
	if (s2!=NULL) if (s2<s) s = s2;
	if (s!=NULL) *s = 0;
	return bf;
}


int cgi_show(void)
{
 	int i;
	for (i=0; i<nquery; i++) {
		hprintf("Query (%s) = (%s)<br>\n",query_name[i],query_val[i]);		
	}
	for (i=0; i<nform; i++) {
		hprintf("Form (%s) = (%s)<br>\n",form_name[i],form_val[i]);		
	}
	return TRUE;
}
