#define BIRTHDAY_PATH "/CHANGE/THIS/PATH/birthday_data"
#define BIRTHDAY_PROGRAM_URL "/CHANGE/THIS/URL/wbw1"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>

/* Month names to show the user */
char *months[12] =
{
  "january", "february", "march", "april", "may", "june",
  "july", "august", "september", "october", "november", "december"
};

/* Month names to search for in the PATH_INFO variable */
char *months_p[12] =
{
  "/january", "/february", "/march", "/april", "/may", "/june",
  "/july", "/august", "/september", "/october", "/november", "/december"
};

/* Forward references */
void Browse();
void OutputMonth(int month);
void OutputDay(int month, int day);
void BirthdayOutput (int day, int month, 
	char *name_s, char *url_s, char *email_s);
void BirthdayHead (char *request);
void BirthdayTail ();
void RemoveSpaces (char *dest, char *src);

int main (int argc, char *argv[])
{
	Browse();
	return 0;
}

void Browse()
{
	time_t now_t;
	int birthdayCount;
	int month, day;
	int i;
	int found = 0;
	char *pathInfo;
	FILE *in;
	char path[161];
	pathInfo = getenv("PATH_INFO");
	if (!pathInfo) {
		strcpy(path, "/");
	} else {
		strcpy(path, pathInfo);
	}
	for (i = 0; (i < 12); i++) {
		/* See if this request matches one of the days of
			the month. If it does, check further to see
			if a specific day is requested. */
		int len = strlen(months_p[i]); 
		if (!strncmp(path, months_p[i], len)) {
			month = i; 
			if (path[len] == '/') {
				int day = atoi(path+len+1);
				if (day) {
					OutputDay(month, day);
					found = 1;
					break;
				}
			}
			OutputMonth(month);
			found = 1;
			break;
		}
	}
	if (!found) {
		struct tm *now_tm;
		/* If we didn't find a request for a specific date,
			then output today's birthdays instead. */
		/* Retrieve the current time */
		time (&now_t);
		/* Break it down into month, day, year and so on */
		now_tm = gmtime (&now_t);
		month = now_tm->tm_mon;
		day = now_tm->tm_mday;
		/* Output today's birthdays */
		OutputDay(month, day);
	}
	printf("<HR>\n");
	printf("<H2>Global Birthday Navigator (GBN)</H2>\n");
	for (i = 0; (i < 12); i++) {
		printf("<A HREF=\"%s/%s\">%s</A> \n",
			BIRTHDAY_PROGRAM_URL, months[i], months[i]);
	}
	printf("<A HREF=\"%s\">today</A>\n", BIRTHDAY_PROGRAM_URL);
	printf("<HR></BODY></HTML>\n");
}

void OutputMonth(int month) 
{
	int i;
	printf("Content-type: text/html\n\n");
	printf("<HTML><HEAD>\n");
	printf("<TITLE>World Birthday Web (WBW): %s</TITLE></HEAD>\n",
		months[month]);
	printf("<BODY><H1>World Birthday Web (WBW): %s</H1>\n", 
		months[month]);
	printf("<H2>Please select a day of the month.</H2>\n");
	printf("<P><HR>\n");
	for (i=1; (i < 32); i++) {
		printf("<A HREF=\"%s/%s/%d\">%d</A> \n",
			BIRTHDAY_PROGRAM_URL, months[month], i, i);
	}
	printf("</BODY></HTML>\n");
}

void OutputDay(int month, int day) {
	FILE *in;
	char path[256];
	int birthdayCount = 0;
	printf("Content-type: text/html\n\n");
	printf("<HTML><HEAD>\n");
	printf("<TITLE>World Birthday Web (WBW)</TITLE></HEAD>\n");
	printf("<BODY><H1>");
	printf("World Birthday Web (WBW)</H1>\n");
	sprintf(path, "%s/%d/%d", BIRTHDAY_PATH, month+1, day);
	in = fopen (path, "r");
	if (in) {
		while (!feof (in)) {
			char name_s[512], url_s[512], email_s[512];
			char nameS[512], urlS[512], emailS[512];
			if (!fgets (name_s, 512, in)) {
				break;
			}
			RemoveSpaces (nameS, name_s);
			if (!fgets (url_s, 512, in)) {
				break;
			}
			RemoveSpaces (urlS, url_s);
			if (!fgets (email_s, 512, in)) {
				break;
			}
			RemoveSpaces (emailS, email_s);
			if (!birthdayCount) {
				char s[81];
				sprintf(s, "%d %s", 
					day, months[month]);
				BirthdayHead (s);
			}
			birthdayCount++;
			BirthdayOutput (day, month,
				nameS, urlS, emailS);
		}
	}
	fclose (in);
	if (birthdayCount) {
		BirthdayTail ();
	} else {
		printf(
		"<em>No birthdays have been entered for this day.</em>\n");
	}
}

void RemoveSpaces(char *dest, char *src) {
	/* Remove all leading and trailing spaces. */
	char *last;

	/* First, skip to the first non-space character 
		in the source string. */
	while (*src) {
		if (!isspace(*src)) {
			break;
		}
		src++;
	}	

	/* Now, copy the source string to the destination string. */
	strcpy(dest, src);

	/* Now, find the last non-space character in the destination string;
		move downward through the string from the end. */
	if (!strlen(dest)) {
		return;
	}	
	last = dest + strlen(dest) - 1;	
	while (last != dest) {
		if (!isspace(*last)) {
			/* We have found the last non-space character
				in the string, so place a final null
				immediately after it. */
			*(last + 1) = '\0';
			break;
		}
		last--;
	}		
}

void BirthdayOutput (int day, int month,
		char *name_s, char *url_s, char *email_s) 
{
	printf("<LI>");
	if (strlen (url_s)) {
		printf("<A HREF=\"%s\">", url_s);
	}
	printf("%d %s: ", day, months[month]);
	printf("<STRONG>%s</STRONG>", name_s);
	if (strlen (email_s)) {
		printf(" <EM>%s</EM>\n", email_s);
	}
	if (strlen (url_s)) {
		printf("</A>\n");
	}
	printf("</LI>\n");
}

void BirthdayHead (char *request) 
{
	printf("<H2>Birthdays for: %s</H2><UL>\n", request);
}

void BirthdayTail () 
{
	printf("</UL>\n");
	printf("<P><em>Remember, the Birthday Server");
	printf("runs on Greenwich Mean Time.</em>\n");
}

