/***************************
 * CGI blockade
 * Written by Michael TUrner
 ***************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <pwd.h>

#include "tools.h"
#include "global.h"
#include "lex.yy.c"

#define HTML_DIR "/private_html/"
/* for what dir to look in */
#define UC unsigned char

int matchp(char *str, unsigned char array[4]) /* specilized for IP numbers */
  {
    int answer = 1;
    int i = 0;
    char *foo, *bar;

    foo = strdup(str);
    bar = (char*)malloc(strlen(foo) * sizeof(char));

    i = 0; while(i < strlen(bar)) bar[i++] = '\0';
    strncpy(bar,&foo[1],strchr(&foo[1],'.') - &foo[1]);
    foo = strchr(&foo[1],'.');

    if(answer && !(bar[0] == '*' || (UC)atoi(bar) == array[0]))
      answer = 0;

    i = strlen(bar); while( i > 0) bar[--i] = 0;
    strncpy(bar,&foo[1],strchr(&foo[1],'.') - &foo[1]);
    foo = strchr(&foo[1],'.');
    if(answer && !(bar[0] == '*' || (UC)atoi(bar) == array[1]))
      answer = 0;

    i = strlen(bar); while( i > 0) bar[--i] = 0;
    strncpy(bar,&foo[1],strchr(&foo[1],'.') - &foo[1]);
    foo = strchr(&foo[1],'.');

    if(answer && !(bar[0] == '*' || (UC)atoi(bar) == array[2]))
      answer = 0;

    i = strlen(bar); while( i > 0) bar[--i] = 0;
    strcpy(bar,&foo[1]);
    if(answer && !(bar[0] == '*' || (UC)atoi(bar) == array[3]))
      answer = 0;
    free(bar);
    return answer;
 
  }

int main()  
  {
    char *cl;
    char *user;
    struct passwd *pass_info;
    char *path_info;
    char *hold_path;
    char *extra;
    char *full_path;
    unsigned char remote[4]; /* the remote address */
    unsigned char test[4]; /* the address testing */
    int answer;
    int accept;
    int printit = 1;
 
    cl = getenv("REMOTE_ADDR");
    if(cl == NULL)
      {
	html_error("No remote address.\n");
	exit(1);
      }
    remote[0] = (char)atoi(strtok(cl,"."));
    remote[1] = (char)atoi(strtok(NULL,"."));
    remote[2] = (char)atoi(strtok(NULL,"."));
    remote[3] = (char)atoi(strtok(NULL,"."));

    cl = getenv("PATH_INFO");
    if(cl == NULL)
      {
	html_error("No extra path.\n");
	exit(1);
      }
    if(strlen(cl) > 64)  /* check for a too long string */
      {
	html_error("extra path too long.\n");
	exit(1);
      }
    path_info = strdup(cl);
    hold_path = strdup(cl);
    user = strtok(path_info,"/"); /* ok, get the first part */
    pass_info = getpwnam(&user[1]);
    if(pass_info == NULL) /* NOTE: if you have a non-default web return */
      {                   /* you might want to change this */
        printf("Content-type: text/html\n\n");
	printf("<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
	printf("<BODY><H1>404 Not Found</H1>\n");
	printf("The requested URL %s was not found on this server.<P>\n",hold_path);
	printf("</BODY>\n");
	exit(1);
      }
    extra = strdup(strtok(NULL,"")); /* get the extra path into something */

    full_path = (char*)malloc(STR_SIZE * sizeof(char));
    if(full_path == 0)
      {
	html_error("Error in malloc.");
	exit(2);
      }
    strcpy(full_path,pass_info->pw_dir);
    strcat(full_path,HTML_DIR);
    strcat(full_path,extra);
    yyin = fopen(full_path,"r");
    if(!yyin) /* and if you have a non standard web error message, */
      {       /* you mgiht want to change this too. */
        printf("Content-type: text/html\n\n");
	printf("<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
	printf("<BODY><H1>404 Not Found</H1>\n");
	printf("The requested URL %s was not found on this server.<P>\n",hold_path);
	printf("</BODY>\n");
	exit(1);
      }

    accept = 1;
    answer = yylex();
    printf("Content-type: text/html\n\n");
    printf("<!-- This cgi bin written by Micael Turner -->\n");
    printf("<!-- m_turner@dax.cs.wisc.edu -->\n");
    while(answer)
      {
	/* printf("%d\t%s\n",answer,yytext); */
	switch(answer)
	  {
	    case RESET:
	      accept = 1;
	      break;
	    case PREVENT:
	      {
		char *foo;
		foo = strchr(&yytext[1],'.'); /* first char is a '.' */
		if (matchp(foo,remote)) accept = 0;
		/* printf("%d %s\n",matchp(foo,remote),foo);*/
	        break;
	      }
	    case ALLOW:
	      {
		char *foo;
		foo = strchr(&yytext[1],'.'); /* first char is a '.' */
		if (matchp(foo,remote)) accept = 1;
		break;
	      }
	    case HIDE:
	      if(!accept) printit = 0;
	      break;
	    case END_HIDE:
	      printit = 1;
	      break;
	    case STRING:
	      if (printit) printf("%s\n",yytext);
	      break;
	  }
	answer = yylex();
      }
    free(full_path); free(path_info); free(extra); free(hold_path);
    return(0);
  }
