Dynamische Dokumente und Forms

Mitunter ist es nicht genug, seine einmal fertig geschriebenen Dokumente immer wieder anzuzeigen, sondern es sollen zum Abfragezeitpunkt "frische" Daten eingefügt werden. Das mag im einfachsten Fall die Anzeige der aktuellen Uhrzeit sein (was aber auch viel einfacher geht), genausogut kann es sich aber auch um eine Datenbankabfrage handeln.

Zur Realisierung bietet der Web-Server das Common Gateway Interface (CGI).

Was ist CGI

Das Common Gateway Interface (CGI) ist eine Schnittstelle zwischen dem WWW-Server und beliebigen ausführbaren Programmen. Es definiert im wesentlichen wie die Informationen an das Programm übergeben werden. Grundsätzlich kann jedes ausführbare Programm über das Common Gateway i Interface angesprochen werden. Da Scripte jedoch viel einfacher zu entwickeln und debuggen sind gehen alle folgenden Bemerkungen nur auf diese ein.

Dokumente in einem bestimmten Verzeichnis (i.a. /cgi-bin) werden vom Server automatisch als ausführbare Programme erkannt.

Wie funktioniert das

Der Server definiert einen Satz Environment Variablen und ruft dann das Programm auf. Die für einfache Anwendungen wichtigsten Variablen sind:
REQUEST_METHOD
Bei Methode GET werden alle Argumente in der Variablen QUERY_STRING übergeben. POST übergibt die Daten an der Standardeingabe.
CONTENT_LENGTH
Nur bei POST, Länge des Datenstroms in Byte.
QUERY_STRING
An die Script-URL mit Fragezeichen (?) angehängte Argumente. Bei GET erledigt das der Browser von allein, bei POST könnten so weitere Argumente übergeben werden.
Egal welche Methode zur Übermittlung gewählt wird, lediglich Ziffern, Buchstaben (keine Umlaute!) und die Zeichen * - . _ werden unverschlüsselt übertragen. Alle anderen Zeichen werden URL-encoded. Das heißt, anstelle des Zeichens wird ein Prozentzeichen (%) gefolgt vom Hexadezimalwert des Zeichens eingefügt. Die einzige Ausnahme davon ist das Leerzeichen, welches als Plus (+) übertragen wird. Aus "Olaf Großmann" wird damit "Olaf+Gro%DFmann".

CGIWRAP

Wie bereits kurz erwähnt erwartet der Server CGI-Programme nur in einem bestimmten Verzeichnis (/cgi-bin). Für "normale" Nutzer besteht dort freilich kein Schreibzugriff. Um ihnen dennoch den Gebrauch eigener CGI-Scripte zu ermöglichen, ist das Programm cgiwrap installiert.

Hinweise

Eigene Scripte

Genug der Vorrede, jetzt geht's richtig los. Mit den folgenden "goldenen" Regeln sollte der Einstieg gelingen.

Welcher Interpreter

Beim Aufruf eines Scripts kann das System nicht wissen wie, d.h. mit welchem Interpreter (Bourne-/Korn-Shell, Perl) dieses abzuarbeiten ist. Die "magische" erste Zeile ist daher ganz wichtig. Ein Bourne-Shell-Script beginnt grundsätzlich mit:
#!/bin/sh
        
Ein Perl-Script beginnt mit:
#!/usr/bin/perl
        
Alternativ kommen auch /bin/ksh für die Korn-Shell, /bin/bash für die Bash oder /bin/csh für die C-Shell in Frage.

Parameterübergabe

Die übergebenen Parameter sind möglicherweise URL-encoded und werden in Abhängigkeit von der Methode POST oder GET entweder in der Variablen QUERY_STRING oder über die Standardeingabe übergeben. Der einfachste Weg damit fertig zu werden ist das Hilfsprogramm cgiparse. Der Aufruf cgiparse -form setzt die Variablen FORM_<name>.

In einem Shell-Script erfolgt der Aufruf mit eval:
eval `/usr/local/bin/cgiparse -form`
        
Hinweise:

  1. Die Angabe des vollständigen Pfades nicht vergessen! Der Server sucht nur in wenigen Systempfaden.
  2. Durch eval wird der Output in das Script uebernommen. Bitte die Back Quotes (`) nicht vergessen!
  3. Die oben angesprochene Möglichkeit Daten mit POST zu übermitteln und gleichzeitig weitere Daten mit Fragezeichen an die URL anzuhängen funktioniert nicht mit cgiparse. Wer das unbedingt benötigt kann mit <input type="hidden"> unsichtbare Felder übermitteln oder muß ein eigenes Programm zum Parsen des Inputs verwenden.

Der Output ist ...

In der Regel wird ein CGI-Script als Output HTML-Text liefern. Vorgeschrieben ist das nicht. Und da der Server deshalb auch nicht wissen kann was kommt, muß zuerst ein Header generiert werden. Im Standardfall genügt
Content-Type: text/html
gefolgt von einer Leerzeile (Diese ist allerdings wesentlich!).

Um komplexere Header zu erzeugen (beispielsweise wenn man festlegen möchte, wie lange das File gültig und damit von anderen Servern gespeichert bleibt) bietet sich das Programm cgiutils an.

Alles zusammen

Das folgende kleine Script soll die aktuelle Zeit anzeigen. Wird ihm als Argument "LANG=de" übergeben, so erfolgt die Ausgabe in deutscher Form, ansonsten wie gewohnt englisch.
#!/bin/sh
#

# 1.Parameter uebernehmen
eval `/usr/local/bin/cgiparse -form`

# 2. HTTP-Header ausgeben, Leerzeile nicht vergessen
echo "Content-Type: text/html"
echo

# 3. HTML-Header
echo "<html><body>"

# 4. das eigentliche Programm
# Zeit in Deutsch?
if [ "$FORM_LANG" = "de" ]; then
  echo "<h2>Die aktuelle Zeit ist</h2>"
  LANG=De_DE
  export LANG
else
  echo "<h2>The current time is</h2>"
fi
date

# 5. Den Abspann nicht vergessen
echo "</body></html>"
        
Der Link im Text muß dann heißen:
current time
<a href="/cgi-bin/cgiwrap/grossm/getdate">
aktuelle Zeit
<a href="/cgi-bin/cgiwrap/grossm/getdate?LANG=de">

Vorsicht mit Programmen

Während Scripte grundsätzlich unter verschiedenen Betriebssystemen ablauffähig sind, ist das bei compilierten Programmen nicht so. Sollen daher eigene Programme (z.B. in Fortran oder C geschrieben) zum Einsatz kommen, so müssen diese unter dem gleichen Betriebssystem übersetzt werden, unter dem auch der Web-Server läuft und die Programme startet. Bei uns ist das Linux. Der passende Login-Server ist die Rcs41.

Forms

Zur Erstellung interaktiver Formulare gibt es das Element <FORM>. Die Beschreibung der einzelnen Eingabefelder (INPUT, SELECT, TEXTAREA) kann jeder HTML-Referenz entnommen werden.

Hier nur einige Hinweise in Zusammenhang mit der CGI-Programmierung:

  1. ACTION sollte immer angegeben werden. In der Regel wird es über cgiwrap auf ein Script im eigenen cgi-bin verweisen.
  2. Paßwort-Felder sind mit Vorsicht zu genießen oder besser ganz zu vermeiden (die Übertragung erfolgt unverschlüsselt).
  3. In einem Dokument kann nur ein <FORM>-Element sein.

Beispiele

Wegen letztgenannter Einschränkung sind die Beispiele in separaten Files.

Es muß nicht immer ein CGI-Script sein...

Für einfache Anwendungen können alternativ auch sogenannte Server Side Includes (SSI) zum Einsatz kommen. SSIs sind spezielle Kommentarzeilen, die vom HTTP-Server gelesen und entsprechend ersetzt werden.

Die Syntax ist:
<!--# befehl parameter="wert" parameter="wert" ... -->
        

Befehle

config
legt Ausgabeformate fest. Config gilt für das gesamte Dokument bzw. bis zum nächsten config.
Parameter:
echo
zeigt eine interne Variable an. Der einzig möglicher Parameter ist var.
exec
führt ein Script aus. Auf den meisten Servern (auch bei uns) standardmäßig gesperrt. Zur Freischaltung beachten Sie bitte die unten stehenden Hinweise.
Parameter:
fsize
zeigt die Größe eines Files an. Parameter sind file und virtual (s. include).
flastmod
zeigt das Datum der letzten Änderung eines Files an. Parameter wieder file und virtual.
include
bindet ein anderes Dokument ein.
Parameter:

Variablen

Folgende interne Variablen stehen zur Verfügung (darunter der aktuelle Wert).
DATE_LOCAL Ortszeit
DATE_GMT Greenwhich-Zeit
LAST_MODIFIED Datum der letzten Änderung am aktuellen File.
DOCUMENT_NAME Name des aktuellen Dokuments
DOCUMENT_URI URL des Dokuments
Zusätzlich werden noch folgenden CGI-Variablen unterstützt:
USER_NAME
DOCUMENT_PATH_INFO
QUERY_STRING_UNESCAPED

SSI-Exec's

Wie bereits erwähnt ist die Exec-Direktive standardmäßig gesperrt. Wenn Sie sicher sind, daß die aufgerufenen Programme keinen Schaden anrichten können (die Programme laufen unter der Kennung www des WWW-Servers), können Sie den Zugriff explizit gestatten.

Der Zugriff läßt sich für ganze Verzeichnisse (incl. Unterverzeichnisse) oder für einzelne Files festlegen.

  1. Ein File .htaccess im entsprechenden Verzeichnis anlegen.
  2. .htaccess für den Web-Server lesbar machen:
    chmod 644 .htaccess
              
  3. Wurde die erste Variante (ohne Files) gewählt und sollen die Unterverzeichnisse ausgeschlossen werden, so muß in jedem Unterverzeichnis ein .htaccess-File mit dem Inhalt
    Options IncludesNoExec
    
    angelegt werden (chmod 644 nicht vergessen!).

Beispiele

  1. Wann wurde das Dokument zuletzt modifiziert?
    Last updated: 
    <!--#echo var="LAST_MODIFIED" -->
              
    Last updated:
  2. Desgleichen, doch Ausgabe der Zeit in deutscher Schreibweise:
    Letzte Änderung am:
    <!--#config timefmt="%d.%m.%Y" -->
    <!--#echo var="LAST_MODIFIED" -->
    	
    Letzte Änderung am:

Olaf Großmann, letzte Änderung am