/* exclock - Ein digitales Allzweck-Uhrprogramm, das die
 * Bibliothek gd1.2 benutzt, um eine Server Push-Animation fr 
 * Netscape 1.1+ zu erzeugen.
 * Die Ausgabe geht an den Standardoutput fr die Nutzung
 * in WWW-Seiten.
 * CGI 1.1/ANSI C, und besteht aus einer Reihe von Bildern im
 * Format GIF89a, fr die Anzeige der lokalen Systemzeit.
 * Das Bild wird interlaced und transparent sein.
 *
 * Anwendung:
 * <IMG SRC="/cgi-bin/nph-exclock"  ALT="Netscape 1.1+ erforderlich" >
 *
 *
 */

/* Copyright 1995 Dan Austin.
 * Dieses Programm wird als Public Domain zur Verfgung gestellt. */

/* Dieses Program verwendet die Bild-Bibliothek GD1.2, Copyright 1994,1995
 * Quest Protein Database Center, Cold Spring Harbor Labs.	
 */ 

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

/* GD Bibliothek-Header */
#include "gd.h"
#include "gdfontl.h"

/* Dies ist der Server Push MIME type */
#define PUSHHEADER "Content-type: multipart/x-mixed-replace;boundary=DELIMIT\n" 

/* Dieser String mu jedes gesendete Multipart-Dokument separieren */
#define DELIMITSTRING "\n--DELIMIT\n"

/* Dieser String sollte nach dem letzten Teil des Multipart-Dokuments gesendet werden */
 #define ENDSTRING "\n--DELIMIT--\n"

/* Der MIME-Typ fr unsere Aufgabe - eine Serie von GIF89-Bildern
 * Beachten Sie, da dieser Zeile zwei neue Zeilenwechsel folgen, um
 * den Browser zu benachrichtigen, da der Inhalt selbst folgt.
 * Das ist erforderlich.
 */
#define GIFSTRING "Content-type: image/gif\n\n"

/* Die maximale Anzahl der Aktualisierungen fr die Uhr.
 * Dies sollte fr alle Programme eingestellt werden, um dem 
 * Programm eine Standard-Endsequenz zu liefern.	
 */
#define MAXCOUNT 1000

/* Wie oft zeigen wir die aktuelle Zeit an (Sekunden)? */
#define REFRESH 1

/* Die maximale Lnge des Zeit-Strings */
#define MAXLEN 22

/* Definiere die RGB-Werte fr die Vordergrundfarbe der Uhr.
 * Die Werte liegen zwischen 0 und 255 und bestimmen die Intensitt.
 * Der Krper der Uhr wird transparent sein.
 */
#define RED 0
#define GREEN 0
#define BLUE 255

/* do_string verwendet die Bild-Bibliothek GD, um ein Bild
 * eines Strings im Format GIF89 zu erzeugen.
 */
void string2gif(char *tstring);
/* do_time formatiert die Zeit zu einem NULL-terminierten String
 * fr die Ausgabe um.*/
void do_time(char *tstring);

int main() 
{
	int count = 0;
	char outstring[MAXLEN];


	/* ermittle, ob wir gerade Mozilla benutzen */
	if(strncmp(getenv("HTTP_USER_AGENT"),"Mozilla/1.",10) == 0)
	{
		/* Seitdem der Server die Datei nicht mehr analysiert,
		 * mssen wir unseren eigenen HTTP Status-Code senden.
		 * In diesem Fall senden wir 200 fr "OK." Manche Server-
		 * Software wird vielleicht dagegen protestieren.
		 * Wenn Sie bei diesem Programm stndig
		 * Fehlermeldungen erhalten,(Symbol fr gebrochenes Bild 
		 * statt der Uhr), versuchen Sie diese Zeile
		 * zu lschen. Weder der Netscape- noch der NCSA-Server
		 * haben dieses Problem.
		 */
		(void)fprintf(stdout,"HTTP/1.0 200\n");

		/* Sag dem Client, da er einen Multipart MIME-Typ
		 * erwarten soll */
		(void)fprintf(stdout,PUSHHEADER);

		/* Sende den ersten abgegrenzten String */
		(void)fprintf(stdout,DELIMITSTRING);

		for (count = 0; count < MAXCOUNT; count++)
		{
			/* do_time formatiert die Lokalzeit zu einem 
			 * Zeichen-string */
			do_time(outstring);

			/* Prfe STDOUT jedes Mal, beende normal, wenn geschlossen
			 * Sei damit paranoid. Das hilft auer Kontrolle
			 * geratenen Prozessen vorzubeugen.
			 */
			if (!feof(stdout))
			{
				/* Gib Typ des Inhalts aus */
				(void)fprintf(stdout,GIFSTRING);
				/* string2gif gibt ein GIF89-Bild an STDOUT aus */
				string2gif(outstring);
			}
			else
				exit(1);

			/* Sende den Multipart-Delimiter */
			(void)fprintf(stdout,DELIMITSTRING);
		sleep(REFRESH);
		}
		/* Sende den Ende-Delimiter-String zum Client */
		(void)fprintf(stdout,ENDSTRING);
	}
	else	/* Mozilla wird nicht benutzt */
	{
		/* Sende ein Standard-Bild zum Browser */
		(void)fprintf(stdout,GIFSTRING);

		/* Hole die Zeit */
		do_time(outstring);
		/* string2gif bertrgt ein GIF89-Bild an STDOUT */
		string2gif(outstring);
	}
	exit(0);
}


/* do_time - Funktion zum Formatieren der lokalen Systemzeit
 * das Format ist :
 * Tag-der-Woche Monat Tag-des-Monats HH:MM:SS am/pm
 * z.B. "Tue Jun 3 19:46:21 pm." 
 */
void do_time(char *outstring)
{
	size_t len;
	time_t now;
	struct tm *ltime;

	len = MAXLEN*sizeof(char);
	now = time(NULL);
	ltime = localtime(&now); 
	strftime(outstring, len, "%a %b %d %I:%M:%S", ltime);
	return;
}


/* string2gif - Funktion, welche die Bibliothek gd1.2 zum Erzeugen
 * eines GIF benutzt, das einen String enthlt.
 * Die Ausgabe geht an STDOUT zur Nutzung in WWW-Seiten.
 * CGI 1.1/ ANSI C
 * 
 * Die hier verwendete Schriftart ist ein 9x15bold, zur Verfgung gestellt mit GD 1.2.
 */

void string2gif(char *outstring) 
{
	gdImagePtr image;
	int bg;
	int fg;
	int len;
	int x;
	int y;	
	int sx;
	int sy;

	/* die Lnge des Strings holen */
	len = strlen (outstring);
	
	/* Erzeuge das Anfangsbild. Achte darauf, da die Gre
	 * der Bilder konstant x und y ist, ansonsten wird eine
	 * Fehlermeldung dabei herauskommen.
	 */
	sx = (gdFontLarge->w) * MAXLEN +5;
	sy = (gdFontLarge->h) +5;
	image = gdImageCreate(sx,sy);

	/* Hintergundfarbe (erste Zuweisung).
	 * Diese wird transparent sein. */
	bg = gdImageColorAllocate(image, 0,0,0); /* Schwarz */

	/* Vordergundfarbe wird blau sein*/
	fg = gdImageColorAllocate(image, RED,GREEN,BLUE);      

	/*  Zentriere den String auf dem Bild */
	x = (image->sx/2) - (len * gdFontLarge->w)/2;
	y = (image->sy/2) - (gdFontLarge->h/2);

	/* Jetzt schreibe den String in die GIF89a-Datei */
	gdImageString(image,gdFontLarge,x,y,outstring,fg);
	
	/* Mach den Hindergrund transparent */
 	gdImageColorTransparent(image, bg);

	/* Interlace das Bild */
	gdImageInterlace(image, 1);
	
	/* Sende das Bild an die Seite */
	if ( !feof(stdout) ) 
		gdImageGif(image,stdout);
	else
		exit(1);
	fflush(stdout); 


	/* Zerstre das Bild im Speicher. */
	gdImageDestroy(image);

	return;
}

