#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef WIN32
/* #include <windows.h>*/
#include <io.h>
#endif
#include <fcntl.h>

#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
#define BFSZ 1000

#define safecpy(a,b) ncpy(a,b,199)

#ifdef unix
char *strlwr(char *s);
void strrev(char *thestr);
#endif

void printvalidstuff(void);
void getsetfeed(char *cmdvar, char *feedfileloc, char *cgiloc);
void printemptyform(char *cgiloc);
void readfile(char *sitenamevar,char *feedfileloc,char *cgiloc, char *passwordvar);
void savefile(char *feedfileloc,char *sitenamevar,char *newgroupsvar);
/*void getfirstline(char *instring,char*newgroupsvar);*/
void strtrm(char *thestr); 
void getlinewithstrinfile(char *theline, char *searchfor,char *thefilename);
char *lib_encode(char *kkkk);
char *value_encode(char *s);
char *mygetenv(char *v);
char *query_find(char *s);
int query_get(void);
void getword(char *word, char *line, char stop) ;
char x2c(char *what) ;
char *email_name(char *email);
void unescape_url(char *url) ;
void plustospace(char *str) ;
void form_get(void);
char *form_find(char *s);
char *ncpy(char *dst, char *src, int len);
int isThisAFileName(char *s);

char thisuser[BFSZ];
char method[BFSZ];

int main(int argc, char *argv[])
{
	char cmdvar[BFSZ],tmpvar[BFSZ],thisuser[BFSZ],
	     feedfileloc[BFSZ], cgiloc[BFSZ], actionvar[BFSZ],
	     sitenamevar[BFSZ],passwordvar[BFSZ];
	char *newgroupsvar;
	
	safecpy(thisuser,mygetenv("REMOTE_USER"));
	safecpy(method,mygetenv("REQUEST_METHOD"));
	strlwr(method);
		
	printf("Pragma: cache\n");	/*print some stuff so that the html is correct*/
	printf("Content-type: text/html\n\n");
	printf("<head><title>Group Update Program</title></head>\n");
	printf("<body><h2>Group Update Program</h2><hr>\n");
					/*read the information from the setfeed.ini file*/
	
	query_get(); /* Get the http:...webcgi.exe?cmd=bbb&person=joe*/
	safecpy(cmdvar,query_find("cmd"));
		
	getsetfeed(cmdvar,feedfileloc,cgiloc);

	if (strcmp(cmdvar,"")==0) 	      /*send passwd&site form*/
	{	printemptyform(cgiloc);
	}
	else if (strcmp(cmdvar,"getinfo")==0) /*do the stuff*/
	{	form_get(); 
		safecpy(sitenamevar,form_find("site"));
		safecpy(passwordvar,form_find("pass"));
		newgroupsvar = form_find("data");
		safecpy(actionvar,form_find("action"));
		if (strlen(sitenamevar)==0) {printf("No site name entered, ");}
		if (strlen(passwordvar)==0) {printf("No password entered, ");}
		if ((strlen(sitenamevar)==0) || (strlen(passwordvar)==0)) 
		{	printf("incorrect form, please try again<br><br>\n");
		}else if (strcmp(method,"post")==0) 
		{	getlinewithstrinfile(tmpvar, sitenamevar, "setfeed.ini");
			if (strstr(tmpvar,sitenamevar)!=NULL) 
			{	memmove(tmpvar,strstr(tmpvar,sitenamevar)+strlen(sitenamevar) ,strlen(tmpvar)-strlen(sitenamevar) );
				 strtrm(tmpvar);
			} else printf("Site \"%s\" is not listed in the setfeed.ini file<br>",sitenamevar);
			if (strcmp(tmpvar,passwordvar)!=0)
				printf("Incorrect Password for site \"%s\"  ",sitenamevar);
			else{
				if (strcmp(actionvar,"Save")==0)
					savefile(feedfileloc,sitenamevar,newgroupsvar);
				else if (strcmp(actionvar,"Enter")==0)
					readfile(sitenamevar,feedfileloc,cgiloc,passwordvar);
				else printf("Unrecognised command = %s\n<br>How did you get this address??????",actionvar);
			}
		} else printf("Unrecognised command = %s\n<br>How did you get this address??????",tmpvar);
	} else if  (strcmp(cmdvar,"valid")==0) 
		printvalidstuff();
	
	/*add trailer to html document     <a HREF=\"%s?cmd=valid\">whats valid?</a>\n*/	
	printf("<br>\n<a HREF=\"%s\"> Let me specify a new site to modify</a><br><hr><small><small>&#169; 1999 NetWin LTD</small></small>\n",cgiloc);
	printf("\n</body>\n");
	return 0;
}

void printvalidstuff(void)
{	printf(	"format of groups specification is:\n<br>\n<br>"
		"[!]<i>group_name</i>[CR[!]<i>group_name</i>[....]]\n<br>\n<br>"
		"where <i>group_name</i> is the name of a group, this includes t"
		"he wild card \"*\". things in [] brackets are optional. "
		"CR is a new line. "
		"The ! symbol means not, so that you can specify all groups, and th"
		"en remove a few specific groups.  \n<br>\n<br>"
		"example1:(all groups)\n<br>*\n<br>\n<br>"
		"example2:(all groups except for the binaries and test groups)\n<br>*<br>!*.binaries*\n<br>"
		"!*.test*\n<br>\n<br>"
		"example3:(essentially specifying each group seperately)\n<br>alt.kittens\n<br>"
		"alt.cats\n<br>"
		"alt.puppies\n<br>"
		"alt.dogs\n<br>....\n<br>\n<br>");
}


#ifdef unix
#define _tolower(_c)    ( (_c)-'A'+'a' )
#define _toupper(_c)    ( (_c)-'a'+'A' )


char *strlwr(char *s)
{
        char *ss=s;
        for (;*s!=0;s++) if (isupper(*s)) *s = _tolower(*s);
        return ss;
}
void strrev(char *thestr)
{	char *start=thestr;
        char *theend=thestr+strlen(thestr)-1;
	char tempchar;
        for (; theend-start>0 ;start++, theend--) 
        {	tempchar=*start;
		*start=*theend;
		*theend=tempchar;
	}
}

#endif



void getsetfeed(char *cmdvar, char *feedfileloc, char *cgiloc)
{	FILE *setfeed;
 	char tmpvar[BFSZ];
	
	safecpy(tmpvar,mygetenv("SCRIPT_NAME"));
	strrev(tmpvar);
	while (((*tmpvar != '\\') && (*tmpvar != '/')) && strlen(tmpvar)>0 )
	{	memmove(tmpvar,tmpvar+1,strlen(tmpvar)+1);
	}
	strrev(tmpvar);
	if (((*tmpvar == '\\') || (*tmpvar == '/')) && strlen(tmpvar)>0 )
	{	memmove(tmpvar,tmpvar+1,strlen(tmpvar)+1);
	}
	strcat(tmpvar, "setfeed.ini");
	setfeed = fopen(tmpvar,"r");
	if (setfeed==NULL) /*try another location*/
	{	setfeed = fopen("setfeed.ini","r"); 
	}
	if (setfeed==NULL) 
	{	printf("I cannot open the very important setfeed.ini file<br>\n");
		printf("Please place it in the same directory as GUPCGI, ie, as %s from your website <br>\n",tmpvar);
		safecpy(cmdvar,"");
	}else /*read the information from the setfeed.ini file*/
	{	while (!feof(setfeed)) 
		{ 	fgets(feedfileloc,200,setfeed);
			strlwr (feedfileloc);
			strtrm (feedfileloc);
			if (strncmp(feedfileloc,"newsfeeds",9)==0)
			{	safecpy(tmpvar,strstr(feedfileloc,"newsfeeds")+10);
				safecpy(feedfileloc,tmpvar);
				break;
			}else	safecpy(feedfileloc,"");
		}
		fseek(setfeed, 0, SEEK_SET);
		while (!feof(setfeed)) 
		{ 	fgets(cgiloc,200,setfeed);
			strlwr (cgiloc);
			strtrm(cgiloc);
			if (strncmp(cgiloc,"machineip",9)==0)
			{	safecpy(tmpvar,strstr(cgiloc,"machineip")+10);
				safecpy(cgiloc,tmpvar);
				break;
			}else	safecpy(cgiloc,"");
		}
		strtrm(cgiloc);
		strtrm(feedfileloc);
		if (strcmp(feedfileloc,"")==0)
			printf("The location of the newsfeeds file is not specified in setfeed.ini file\n");
		if (strcmp(cgiloc,"")==0)
			safecpy(cgiloc,mygetenv("SCRIPT_NAME"));
	}
}

void printemptyform(char *cgiloc)
{	printf("<nobr><form name=\"indexform\" method=\"post\" action=\"%s?cmd=getinfo\">"
	"Please enter your password "
	"<input type=\"password\" name=\"pass\" size=\"16\" maxlength=\"16\">"
	" for the site <input type=\"text\" name=\"site\" size=\"35\" maxlength=\"35\">"
	"<input type=\"submit\" name=action value=\"Enter\">"
	"</form></nobr>",cgiloc);
}                                                                          


int isThisAFileName(char *s){
	while (*s != 0){
		if (*s == '\\' || *s == '/')
			return 0;
		if (*s == ',')
			return -1;
		s++;
	}
	return -1;
}

void readfile(char *sitenamevar,char *feedfileloc,char *cgiloc,char *passwordvar)
{	FILE *feedfile;
	FILE *realfile;
	char searchfor[BFSZ],instring[BFSZ],c;
	int doneit = FALSE,foundsite = FALSE;
	int searchforlen;
	safecpy(searchfor,"site ");
	strcat(searchfor,sitenamevar);
	strlwr(searchfor);
	searchforlen = strlen(searchfor);
	feedfile = fopen(feedfileloc,"r");
	if (feedfile==NULL) {
	 	printf("Unable to open newsfeeds.conf<br>");
	 	printf("You may need to change the ownership/protection on (%s) and the directory containing that file<br>\n",feedfileloc);
	}else{
		while (!feof(feedfile) && doneit==FALSE){
			fgets(instring,199,feedfile);
			strtrm(instring);
			strlwr(instring);
			if (strncmp( instring, searchfor, searchforlen)==0) 
				foundsite=TRUE;
			if (strncmp( instring, "groups", 6)==0 && foundsite==TRUE) 
			{	if (isThisAFileName(instring+7)==0)
				{	realfile = fopen(instring+7,"r");
					if (realfile == NULL){
						printf("Could not open the file containing your groups. <br>");
					}else{
						printf("<form method=\"POST\" action=\"%s?cmd=getinfo\">",cgiloc);
						printf("Groups <textarea cols=50 name=\"data\" rows=10 wrap=physical >");
						while (!feof(realfile)){
							c = fgetc(realfile);
							if (c != -1) printf("%c", c);
							else break;
						}
						fclose(realfile);
						printf("</textarea>");
						printf("<br><input type=\"submit\" name=action value=\"Save\"><br>");
						doneit=TRUE;
					}
				}else{
					printf("Your site does not appear to contain a filename.<br>");
				}
				break;
			}
		}
		fclose(feedfile);
	}
	if (feedfile == NULL)	 
	{	printf("could not open file {%s}<br>", feedfileloc);
	}
	if (doneit==TRUE) 
	{	printf("<input type=hidden name=\"site\" value=\"%s\" ><input type=hidden name=\"pass\" value=\"%s\" ></form>",sitenamevar,passwordvar);
		printf("<a HREF=\"%s?cmd=valid\">What can I specify?</a>\n",cgiloc);
	}
	if (foundsite == FALSE) 
		printf("This site is not in the newsfeeds.conf file and you have it listed in setfeeds.ini <br>");
}


void savefile(char *feedfileloc,char *sitenamevar,char *newgroupsvar){
	FILE *feedfile;
	FILE *realfile;
	char searchfor[BFSZ],instring[BFSZ];
	char *comma;
	int foundsite,doneit,searchforlen;

	safecpy(searchfor,"site ");
	strcat(searchfor,sitenamevar);
	strlwr(searchfor);
	searchforlen = strlen(searchfor);
	foundsite = FALSE;
	doneit = FALSE;


	if (strstr(newgroupsvar, ",") != NULL){
		printf("The format does not allow commas, each identifier should be on its own line.<br>");
		printf("The old format allowed &quot*,!*binaries*,!*sex*,*sci*&quot<br>");
		printf("The new format requires each rule to be o its own line e.g.<br>*<br>!*binaries*<br>!*sex*<br>*sci*<br><br>");
		printf("Information has been saved as is indicated below, please use the back button on your web browser to correct it if necessary.");
		while (doneit == FALSE){
			comma = strstr(newgroupsvar, ",");
			if (comma == NULL) 
				break;
			*comma = '\n';
		}
		printf("The information that was saved is:<br>\n");
		printf("<pre>%s</pre>", newgroupsvar);
	}



	feedfile = fopen(feedfileloc,"r");
	if (feedfile != NULL) 
	{	while (!feof(feedfile) && doneit==FALSE) 
		{	fgets(instring,198,feedfile);
			strtrm(instring);
			strlwr(instring);
			if (strncmp( instring, "site", 4)==0) 
				foundsite = FALSE;
			if (strncmp( instring, searchfor, searchforlen)==0) 
				foundsite = TRUE;		
			if (strncmp( instring, "groups", 6)==0 && foundsite==TRUE) 
			{	if (isThisAFileName(instring+7)==0)
				{	realfile = fopen(instring+7,"w");
					if (realfile != NULL) 
					{	fputs(newgroupsvar,realfile);
						printf("Information has been saved.");
						fclose(realfile);  
					}else printf("Could not open your site file {%s} for saving group information",instring+7);
				}else{
					printf("Your site does not appear to contain a filename.<br>");
				}
				break;
			}
		}
		fclose(feedfile);
	}else printf("Could not open the file {%s} for reading information",feedfileloc);
}

/*
void getfirstline(char *instring,char *newgroupsvar)
{	char *place;

	place=strstr(newgroupsvar,"\n");
	if (place==NULL)
	{	safecpy(instring,"");
	}else
	{	strncpy(instring,newgroupsvar,place-newgroupsvar);
		instring[place-newgroupsvar]=0;
		memmove(newgroupsvar,newgroupsvar+strlen(instring)+1,strlen(newgroupsvar+strlen(instring)));
		strtrm(instring);
	}
}*/
		     

void strtrm(char *thestr) /*trim off tailing and precedeing spaces,tabs, CR, and LF */		
{	char tmpvar[BFSZ];
	strrev(thestr);
	while ((thestr[0]=='\r') || (thestr[0]=='\n') || (thestr[0]==' ') || (thestr[0]=='	')) 
		{strcpy (tmpvar,thestr+1);strcpy (thestr,tmpvar);}
	strrev(thestr);
	while ((thestr[0]=='\r') || (thestr[0]=='\n') || (thestr[0]==' ') || (thestr[0]=='	')) 
		{strcpy (tmpvar,thestr+1);strcpy (thestr,tmpvar);}
}

void getlinewithstrinfile(char *theline, char *searchfor,char *thefilename)
{
	FILE *thefile;
	int doneit=FALSE;
	char tmpstr[1270];
	thefile=fopen(thefilename,"r");
	if (thefile==NULL)
		{printf("The file \"%s\" could not be opened",thefilename);}
	else
	{
		while (!feof(thefile) && doneit==FALSE) 
		{
			fgets(tmpstr,126,thefile);  
			strtrm(tmpstr);
			if (strncmp(tmpstr,"site",4)==0) {
			 if (strstr(tmpstr,searchfor)!=NULL) 
		 		{safecpy(theline,tmpstr);doneit=TRUE;}
			}
		}
	if (doneit=FALSE) 
	 {printf("Could not find the text \"%s\" in the file \"%s\"",searchfor,thefilename);}
	fclose (thefile);
	}
}



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

static char *query_name[1000];
static char *query_val[1000];
static int nquery;
/* Query string */
char *lib_encode(char *s)
{
   char *ss=s;
  for (;*s!=0;s++) {
    if (isspace(*s)) *s = '+';
  }
  return ss;
}
char *value_encode(char *s)
{
 	static char bf[2000];
	int i;
	char *out=bf;
	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 *out++ = *s;
	}
	*out++ = 0;
	return bf;
}


char *mygetenv(char *v)
{
	char *s = getenv(v);
	if (s==NULL) return "";
	return s;
}
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_get(void)
{
	char *q;
	char *cl;
	char bf[10000],val[6000],name[6000];
	int x;

	q =  mygetenv("QUERY_STRING");
	if (q==NULL) return FALSE;
	ncpy(bf,q,5000); cl = bf;
    	for(x=0;cl[0] != '\0';) {
    		getword(val,cl,'&');
    		plustospace(val);
        	unescape_url(val);
        	getword(name,val,'=');
		if (strlen(name)>199) continue;
		if (strlen(val)>199) continue; 
		query_name[x] = strdup(name);
		query_val[x] = strdup(val);
		x++;
	/*	printf("[%d] {%s} = {%s} \n",x,query_name[x],query_val[x]);*/
    	}
	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 *makeword(char *line, char stop) ;
char *fmakeword(FILE *f, char stop, int *cl);
void convert_crlf(char *s); /* turn crlf into lf's */
void form_get(void)
{
	int x,cl;
	char *s = mygetenv("CONTENT_LENGTH");
	if (s==NULL) return;
	cl = atoi(s);
	for(x=0;cl && (!feof(stdin));) {
	        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]);
		if (strlen(form_val[x])>999) continue;
		if (strlen(form_name[x])>999) continue;
		x++;
	}
	nform = x;
}
void convert_crlf(char *s)
{
	char *out=s;
	for (;*s!=0;s++) {
		if (*s == '\015') 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;
    }
}


char *form_find(char *s)
{
 	int i;
	for (i=0; i<nform; i++) if (strcmp(form_name[i],s)==0) return form_val[i];
	return "";
}
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) {
		safecpy(bf,s+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;
}



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 *ncpy(char *dst, char *src, int len)
{
        char *xdst = dst;
        int xlen = len;
        for (;(*src !=0) && (len>0); ) {*dst++  = *src++; len--;}
        *dst++ = 0;
        xdst[xlen] = 0;
        return xdst;
}
#ifdef NEED_MEMMOVE
void *memmove(char *dst, char *src, int len)
{
        bcopy(src,dst,len);
        return (void *) dst;
}
#endif
