/* Example custom web server for timedate.com */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <signal.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>

#include "hitsubs.h"
#include "readline.h"

/* This is the HTTP header we need to send to let the browser 
   know we will be sending HTML
*/

char *http_header = "HTTP/1.0 200 OK\nContent-type: text/html\n\n";


/* This is some HTML we always send (goes at the top of each page) */

char *html_header = 
"<TITLE>timedate.com - your personal time provider</TITLE>\n"
"<BODY BGCOLOR=#FFFFFF>\n"
"<CENTER><H1><FONT COLOR=BLUE>Welcome to timedate.com</FONT>"
"<FONT SIZE=-1 COLOR=RED> &nbsp &nbsp &nbsp * Now Y2Kapable!</FONT></H1>\n"
"<H2><I>\"time to get a new fence\"</I></H2>\n"
"<HR WIDTH=80%></CENTER>\n\n";


void sock_printf(int sock, char *fmt, ...)
{
    va_list argp;
    char obuf[2000];

    va_start(argp,fmt);
    vsprintf(obuf,fmt,argp);
    va_end(argp);
    write(sock,obuf,strlen(obuf));
}


void html_error(int sock, char *s ) {
  sock_printf(sock,"%s",http_header); 
  sock_printf(sock,"<H1>Errors Happen!</H1><BR>\n%s\n",s);
}


char *dow[] = {
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday"
};

char *months[] = {
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December"
};


void process_request(int sock,int mon, int day, int year, struct tm *t) {
  int *hits_per_hour;
  int i;
  /* Start with the HTTP header */

  sock_printf(sock,"%s",http_header); 

  /* Now print the HTML header */
  sock_printf(sock,"%s",html_header);

  /* Now print the time and date */
  sock_printf(sock,"<H3 ALIGN=CENTER>It is now: %d:%d</H3>\n",
	 t->tm_hour,t->tm_min);

  sock_printf(sock,"<H3 ALIGN=CENTER>Today is: %s, %s %d, %d</H3>\n",
	 dow[t->tm_wday],
	 months[t->tm_mon],
	 t->tm_mday,
	 t->tm_year+1900);

  if ((hits_per_hour = hits_for_date(mon+1,day,year))!=NULL) {

  /* print the hitlist */
    sock_printf(sock,"<BR><HR><BR>\n");
    sock_printf(sock,"<TABLE BGCOLOR=LIGHTBLUE ALIGN=CENTER BORDER=2\n");
    sock_printf(sock,"<TR><TD COLSPAN=5 VALIGN=MIDDLE ALIGN=CENTER><H3><FONT COLOR=RED>Hit List for %s %d, %d</FONT></H3></TD></TR>\n",
		months[mon],day,year);
    sock_printf(sock,"<TR ALIGN=CENTER><TH WIDTH=100>Hour</TH><TH WIDTH=100>Hits</TH>\n");
    sock_printf(sock,"<TH &nbsp &nbsp &nbsp></TH><TH WIDTH=100>Hour</TH><TH WIDTH=100>Hits</TH></TR>\n");
    for (i=0;i<12;i++) {
      sock_printf(sock,"<TR ALIGN=CENTER><TD>%d-%d:00</TD><TD>%d</TD>\n",
		  i,i+1,hits_per_hour[i]);
      sock_printf(sock,"<TD></TD>");
      sock_printf(sock,"<TD>%d-%d:00</TD><TD>%d</TD></TR>\n",
		  i+12,i+13,hits_per_hour[i+12]);
    }
    sock_printf(sock,"</TABLE>\n");
  }
}



void handle_client( int sock ) {
  char request[1000];
  char *ptr;
  int mon,day,year;
  struct tm *timerec;
  time_t t;

  /* get the current time and date */

  t = time(NULL);
  timerec = localtime( &t );

  /* record the hit and read the hit database */
printf("RECORDING THE HIT\n");
 if ( hit_me()==0) {
   printf("ERROR HITTING WAS %s \n", hiterrorstr());
 }
  /* Now get the request */

  if (readline(sock,request,1000)<=0) {
    /* client gone or error - quit */
    return;
  }

  /* parse the html request */

  /* find the request method */
  if ((ptr = strtok(request," "))==NULL) {
    html_error(sock,"Invalid request");
    return;
  }

  if (strncasecmp(ptr,"get",3)!=0) {
    html_error(sock,"Invalid request");
    return;
  }
      
  /* again should get the resource */
  if ((ptr = strtok(NULL," "))==NULL) {
      html_error(sock,"Invalid request");
      return;
  }

  /* ptr should now point to the resource name */

  if (*ptr != '/') {
    /* invalid request - pretend just asking for / */
    strcpy(ptr,"/");
  }

  if (3 == sscanf(ptr,"/%d/%d/%d",&mon,&day,&year)) {
    process_request(sock,mon-1,day,year,timerec);
  } else {
    /* not a full request - just send back today's hitlist */
    process_request(sock,timerec->tm_mon, timerec->tm_mday, 
	      timerec->tm_year+1900,timerec); 
  }
  return;
}


  
/* Server main routine

   1. create a socket
   2. bind the socket and print out the port number assigned
   3. put the socket into passive mode (listen)
   4. do forever
        get next connection
        handle the connection 
      enddo

*/

void sigcld_handler( int s ) {
  int c;
  wait(&c);
}



int main()
{
  int ld,sd;
  struct sockaddr_in skaddr;
  struct sockaddr_in from;
  int addrlen,length;
  int skip;


  signal(SIGCLD,sigcld_handler);


/* create a socket 
       IP protocol family (PF_INET) 
       TCP protocol (SOCK_STREAM)
*/
  
  if ((ld = socket( PF_INET, SOCK_STREAM, 0 )) < 0)
      {
	perror("Problem creating socket\n");
	exit(1);
      }
  
/* establish our address 
   address family is AF_INET
   our IP address is INADDR_ANY (any of our IP addresses)
   the port number is assigned by the kernel 
*/

  skaddr.sin_family = AF_INET;
  skaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  skaddr.sin_port = htons(0);

  if (bind(ld, (struct sockaddr *) &skaddr, sizeof(skaddr))<0)
      {
	perror("Problem binding\n");
	exit(0);
      }
  
/* find out what port we were assigned and print it out */

  length = sizeof( skaddr );
  if (getsockname(ld, (struct sockaddr *) &skaddr, &length)<0)
      {
	perror("Error getsockname\n");
	exit(1);
      }
  printf("The Server passive socket port number is %d\n",ntohs(skaddr.sin_port));

/* put the socket into passive mode (waiting for connections) */

  if (listen(ld,5) < 0 )
      {
	perror("Error calling listen\n");
	exit(1);
      }
  
/* now process incoming connections forever ... */

  while (1)
    {
      skip=0;
      addrlen=sizeof(skaddr);
      if ( (sd = accept( ld, (struct sockaddr*) &from, &addrlen)) < 0) {
	  if (errno==EINTR)
	    skip=1;
	  else {
	    perror("Problem with accept call\n");
	    exit(1);
	  }
      }

      /*      if ((!skip) && (fork()==0)) {
	close(ld);
	handle_client(sd);
	exit(0);
      } else {
	close(sd);
      }
      */
      printf("GOT A CLIENT\n");
      if (!skip) {
	handle_client(sd);
	close(sd);
      }
    }
}

