CGI

Mario Mühlehner

1. Einleitung

    CGI wird im Zusammenhang mit HTML-Programmierung gerne in einem Atemzug genannt. Für viele Anwendungen im Internetbereich gab bzw. gibt es kein Vorbeikommen an CGI – von einfachen Gästebüchern bis hin zu aufwendigen Datenbankanbindungen (etwa Web-Shops, webbasierten Expertensystemen, etc.).

    Die Ausgangsposition wird dabei durch HTML definiert, die Sprache, in der Web-Dokumente verfasst werden. Die Entwicklung von HTML geht auf die Achziger-Jahre zurück und ist dementsprechend aus heutiger Sicht von einigen Mängeln geprägt. Der Nachteil, der den Grund für diese Abhandlung bildet, ist grundlegend und immer noch Gegenstand von Neuentwicklungen (vgl. Dynamic HTML): HTML ist statisch, d.h. ein HTML-Dokument verändert sein Aussehen in seinem Lebenszyklus nie. Aus diesem Grund ist es auch prinzipiell unmöglich, Variablen zu definieren, in andere Zustände überzuwechseln, Informationen aus beliebiger Quelle dynamisch innerhalb eines HTML-Dokumentes darzustellen. CGI stellt den ersten Ansatz dar, dieses Problem in den Griff zu bekommen.

2. Das Common Gateway Interface

CGI (Common Gateway Interface – Allgemeine Vermittlungsrechner-Schnittstelle) ist eine Möglichkeit, Programme im WWW bereitzustellen, die von HTML-Dateien aus aufgerufen werden können, und die selbst HTML-Code erzeugen und an einen WWW-Browser senden können.

 

    CGI schematisch

    "dynamisches" HTML durch CGI

    Im Klartext heißt das: Man umschifft das Handicap des statischen HTML dadurch, daß man einem Server, der ein ausführbares Programm (unser Gateway) bereitstellt, Information via HTTP schickt, damit dieser aufgrund der ihm zugesandten Informationen eine neue HTML-Seite generiert und an den rufenden Client zurückschickt. Damit ist eine HTML-Seite nicht mehr länger unveränderbar: auf Knopfdruck werden Daten zu einem Server geschickt, dort ausgewertet und anschließend zum Beispiel als Grafik angezeigt. Der Begriff "ausführbar" im Zusammenhang mit unserem Gateway-Programm ist nicht im engeren Sinn aufzufassen: es kann sich dabei auch um interpretierte Programme, sogenannte Skripts, handeln. Mehr dazu aber später im Kapitel 6 - Erstellen von CGI-Programmen.

3. Anforderungen

    Was wird alles benötigt, um ein CGI-Programm von einer Web-Seite aus starten zu können?

    Zuallererst muß ein CGI-fähiger Web-Server existieren. Vertreter dieser Gattung sind z.B. NCSA HTTPd, Apache Server, OmniHTTPd. Letzterer ist besonders einfach zu bedienen und daher bestens zum lokalen Testen von CGI-Programmen geeignet; die Software steht kostenlos zum Download zur Verfügung (siehe Links).

    Als nächstens brauchen wir nur mehr ein CGI-Programm, daß auf unserem Web-Server im Verzeichnis CGI-BIN bzw. im Verzeichnis CGI-LOCAL liegt (dazu später mehr), und eine HTML-Seite, die unser CGI-Programm benutzt. Letztere wird höchstwahrscheinlich ein Formular enthalten, welches den Input für das CGI-Programm bereitstellt.

    Zum Beispiel könnte es sich dabei um folgendes Miniformular am Kopf einer HTML Seite handeln:

    Hier ist es möglich, einen oder mehrere Suchbegriffe einzugeben, um die Seiten der Homepage zu Tage zu fördern, auf denen der bzw. die Begriffe vorkommen. Wir wollen uns an diesem Beispiel skizzenhaft ansehen, wie es zur Wechselwirkung HTML-Seite ó CGI-Programm kommt.

4. Formulare und CGI

    Für unser Suchbeispiel stellt sich der Formularbereich im HTML-Dokument wie folgt dar:

    <form name="SearchForm" action="/cgi-bin/search.pl" method="get">
    <div align="right"><font face="Verdana" size="2"> Suchbegriff:</font>
    <input type="text" name="SearchText">
    <input type="submit" name="SubmitSearch" value="Suchen!">
    </div>
    </form>

    Innerhalb der Form-Tags werden zwei Formularobjekte definiert: das Textfeld SearchText, das den Suchbegriff aufnehmen soll, und der Button SubmitSearch, um die Suchdaten zu übermitteln und die Suche einzuleiten. Wer schon mit Formularen gearbeitet hat, ist mit dem Schema des o.a. Code-Fragments vertraut. Abweichungen können sich aber bei der Art der Übertragung der Daten ergeben: bei einfachen Bestellformularen wird gerne die mailto - Aktion benützt, um die Formulardaten via e-Mail an eine beliebige Adresse zu schicken. Die e-Mail enthält (neben einer frei spezifizierbaren Subject-Zeile) die Daten in folgender Form:

    Formularobjekt1-Name "=" Formularobjekt1-Wert
    Formularobjekt2-Name "=" Formularobjekt2-Wert
    usw.

    In unserem Fall wollen wir unseren Suchbegriff aber nicht per e-Mail abschicken (dies könnte zu längeren Antwortzeiten führen), sondern eben über CGI an unseren Server übermitteln. Der Hinweis auf unser Gateway liegt im action-Attribut des Form-Tags: "/cgi-bin/ search.pl" bezeichnet das Programm, das unsere Suchdaten verarbeiten soll. In diesem Fall wurde die Pfadinformation relativ zu unserem HTML-Dokument angegeben, d.h. HTML-Seite und CGI-Programm liegen auf demselben Server, das Programm im Verzeichnis cgi-bin, das HTML-Dokument im nächst äußeren Verzeichnis. Es ist aber auch zulässig, eine absolute Referenz auf das CGI-Programm zu verwenden (etwa wenn das Programm auf einem anderen Server läuft).

    Noch nicht angesprochen wurde das method-Attribut; es legt fest, wie das CGI Programm die Formulardaten erhält.

5. Grundlagen des Common Gateway Interface

Wir haben bis jetzt diskutiert, wie von HTML aus ein CGI-Programm gestartet werden kann. Allerdings blieb die Frage offen, wie Parameter an das CGI-Programm übermittelt werden können. Dies wird im method-Attribut des Form-Tags eingestellt, wobei zwei Möglichkeiten existieren, die je nach Anwendungsfall unterschiedlich gut geeignet sind.

Die GET-Methode setzt voraus, daß die Parameter in einem String direkt hinter der URL, die das CGI-Programm referenziert, kodiert werden. Als Trennzeichen fungiert das Fragezeichen. Dieser String wird vom CGI-Server in einer Umgebungsvariable (QUERY_STRING) abgelegt und kann über Zugriffe auf Betriebssystemebene ausgelesen werden.

Bsp.: <A HREF="/cgi-bin/program.pl?user=Larry%20Bird&
age=35&pass=testing">CGI Program</A>

Wählt man die POST-Methode, werden alle Formulardaten in der Form

Formularobjekt1-Name "=" Formularobjekt1-Wert &
Formularobjekt2-Name "=" Formularobjekt2-Wert &
usw.

direkt an den CGI-Server geschickt; das dortige CGI-Programm kann daher die Daten über STDIN einlesen.

Bemerkungen zu GET und POST

Ein Vorteil von GET ist, daß es auch ohne Formular in HTML zu verwenden ist. Wie das o.a. Beispiel zeigt, können direkt im HTML-Text Links eingebaut werden, die ein CGI-Programm starten und es gleich mit Parametern versorgen. Nachteilig wirkt sich aber aus, daß Browser (aber auch der Server) unter Umständen die Zeichenketten abschneiden, wenn sie eine bestimmte Länge überschreiten. Daher ist die Anzahl der zu übermittelnden Parameter begrenzt. Die POST-Methode auf der anderen Seite ist für die Verwendung mit Formularen bestimmt. Sie erlaubt die Übergabe von beliebig langer Information und kennt daher Einschränkungen wie die der GET-Methode nicht. Beide Varianten benutzen aber die URL-Codierung.

Anmerkung: Wenn man ein CGI-Programm verfassen will, das sowohl GET- als auch POST-Requests verarbeiten soll, ist es möglich, über Umgebungsvariablen die Art der Anfrage herauszufinden.

Umgebungsvariablen

Die Umgebungsvariablen stellen die Basis des Common Gateway Interface dar. Zum einen fungieren sie als globale Variablen, die Parameter enthalten (vgl. QUERY_STRING nach GET-Anforderung), zum anderen erlauben sie den Zugriff auf verschiedenste Informationen, die sowohl Server als auch Client betreffen.

Es folgt eine Übersicht der CGI – Umgebungsvariablen.

6. Erstellen von CGI-Programmen

CGI wird meist mit einer Skript-Sprache gleichgesetzt, die am Server die Anfragen der Clients bedient. CGI legt lediglich den Standard fest, wie der Datenaustausch zwischen Client und Server auf Basis des HTTP stattfindet und legt dazu Schnittstellen fest; in welcher Sprache ein CGI-Programm verfasst wird, ist aber gleichgültig. Erforderlich sind aber in jedem Fall der Zugriff auf Betriebssystemebene (Umgebungsvariablen, STDIN, STDOUT), wünschenswert die Möglichkeit zur bequemen Stringmanipulation (ausreichend für viele einfache Anwendungen wie Gästebuch, Listenverwaltung, usw.) und zum Aufruf von externen Anwendungen.

Unter häufig verwendeten Vertretern befinden sich unter anderem:

AppleScript
VisualBasic
C/C++
Tcl
Perl

Skriptsprachen wie Perl, Tcl, usw. sind bei schneller Einarbeitung relativ einfach zu bedienen und setzen dabei ein Minimum an Werkzeugen bzw. Kenntnis deren Bedienung voraus. Dies erklärt die Beliebtheit der Skriptsprachen wie etwa Perl – aus diesem Grund ist in der Literatur auch oft von CGI-Skripts die Rede, obwohl CGI keinesfalls auf eine Programmiersprache festgelegt ist. In der Folge werden wir uns exemplarisch mit Perl-Skripts bzw. mit C-Programmen auseinandersetzen.

Verarbeiten von Anfragen:

Wie schon diskutiert, unterscheidet man zwischen Anfragen, die mit der GET- bzw. der POST-Methode übermittelt wurden.

Perl:
$myRequest = $ENV{'QUERY_STRING'};

C:
myRequest = getenv ("QUERY_STRING");

Perl:
$size_of_form_information = $ENV{'CONTENT_LENGTH'};
read (STDIN, $myRequest, $size_of_form_information);

C:
size_of_form_information = getenv("CONTENT_LENGTH")
fread(myRequest, size_of_form_information, 1, stdin)

Erzeugen von HTML-Dokumenten

HTML-Dokumente werden in CGI erzeugt, indem man ihren Source-Code Zeile für Zeile auf STDOUT schreibt. Da sie in diesem Fall "on the fly" generiert werden, spricht man auch von virtuellen Dokumenten.

Perl:
print "Content-type: text/html", "\n\n";
print "<HTML>", "\n";
print "<HEAD><TITLE>Virtual HTML Document</TITLE></HEAD>", "\n";
print "<BODY>", "\n";
print "Hello World!", "\n";
print "</BODY></HTML>", "\n";

C:
printf ("Content-type: text/html\n\n");
printf ("<HTML>\n");
printf ("<HEAD><TITLE>Virtual HTML Document</TITLE></HEAD> \n");
printf ("<BODY>\n");
printf ("Hello World!\n");
printf ("</BODY></HTML>\n");

Abgesehen von kleinen syntaktischen Unterschieden sind beide Programm-Fragmente sehr ähnlich, insbesondere die jeweils erste Anweisung. Diese stellt nämlich die sogenannte Header-Information dar, die dem Server mitteilt, wie die nachfolgenden Daten zu interpretieren sind. Neben der oben verwendeten Möglichkeit, direkt HTML-Dokumente zu generieren, kommen aber noch weitere Optionen in Frage, die mit folgenden Headern eingestellt werden können.

Bsp. (Perl):

#!/usr/local/bin/perl
$gif_image = join ("/", $ENV{'DOCUMENT_ROOT'}, "icons/tiger.gif");
if (open (IMAGE, "<" . $gif_image)) {
$no_bytes = (stat ($gif_image))[7];
print "Content-type: image/gif", "\n";
print "Content-length: $no_bytes", "\n\n";
print <IMAGE>;
} else {
print "Content-type: text/plain", "\n\n";
print "Sorry! I cannot open the file
$gif_image!", "\n";
}
exit (0);

Bsp. (Perl):

#!/usr/local/bin/perl
print "Location: /Message.html", "\n\n";
exit (0);

 

Anmerkung:
Wie in o.a. Beispielen ersichtlich, ist es unbedingt erforderlich, die Header-Information durch eine Leerzeile (vgl. \n\n) vom restlichen Skript abzutrennen. Ansonsten interpretiert der Server das ganze Skript als Header und generiert in Folge einen Server error.

7. CGI und Sicherheit

    Sicherheitslücken sind in einem System nie vollständig auszuschließen. Leider gibt es im Zusammenhang mit CGI und Formularen Mängel, die potentielle Risiken darstellen.

    In diese Kategorie fällt etwa die Übertragung von Benutzerinformation. Oft möchte man zum Beispiel nur einem begrenzten Benutzerkreis gegen Identifikation den Zugang zu bestimmten Informationen gewähren. Dies wird meist so gelöst, daß in einem Formular Benutzername und Kennwort abgefragt werden, um anschließend an ein CGI-Programm geschickt und dort ausgewertet zu werden. Unglücklicherweise gehen die Benutzerdaten jedoch unverschlüsselt über das Internet – damit kann Mißbrauch nicht ausgeschlossen werden.

    Gefährlich ist auch folgendes:

    print `$query_string`;

    Gefährlich deswegen, weil ein trickreicher Benutzer folgendes Systemkommando eingeben könnte:

    rm -fr /

    Damit hätte der Server-Administrator auf jeden Fall wieder genügend Speicherplatz auf der Harddisk zur Verfügung. Man sollte generell den Eingaben der Benutzer mißtrauisch gegenüberstehen. Angenommen, wir hätten in unserem Perl-Skript folgende Zeile:

    system "finger $username" ;

    Wenn der geneigte User nun "james; rm -rf /" als Usernamen eingibt, wird daraus

    system "finger james; rm -rf /" ;

    was obigem Beispiel entspricht. Das Gebot der Stunde ist deshalb, die Eingaben auf Steuerzeichen (Semikolon, Slash, Backslash, usw.) zu prüfen, um Mißbrauch vorzubeugen.

8. Zusammenfassung

CGI ist für einen Web-Server das "Tor zur Welt"; dementsprechend kann man die Aufgaben eines CGI-Programmes einteilen in

      1. das Empfangen von Benutzerdaten (beim Aufruf),
      2. das Verarbeiten dieser Benutzerdaten,
      3. die Ausgabe von Daten über den Web-Server.

Das Common Gateway Interface ist der Standard für den Datenaustausch und auf keine spezielle Programmiersprache festgelegt. Der Standard legt fest, wie auf bestimmte Ressourcen des Servers bzw. Clients zugegriffen werden kann; dabei ist aber zu beachten, daß sich nicht alle Browser daran halten.

Der CGI-Output umfasst alle denkbaren Dokumenttypen; neben einfachen HTML-Dokumenten können auch Video-Clips, Audio-Daten und vieles mehr zum Client zurückgeschickt werden. Dabei kann man entweder den Output dynamisch durch das CGI-Programm erzeugen (virtuelles Dokument), oder den Server durch Umleitung (Server Redirection) auf bestehende Ressourcen zugreifen lassen.

Mithilfe der Interaktion zwischen Client und Server via CGI können somit dynamische Dokumente (im Sinne von Benutzerinteraktion) erstellt werden und dadurch das statische Wesen von HTML umgangen werden.

I. Glossar

MIME
Multipurpose Internet Mail Extensions – grundlegende Dokumenttypen, z.B. text/html, image/gif, image/jpeg, usw.

Server redirection
Statt ein Dokument zu generieren, wird ein auf dem Server liegendes Dokument zum Client geschickt – bei statischer Information effizienter.

STDIN
Kanal, über den die Eingaben erfolgen. Hier nur bei POST benutzt.

STDOUT
Kanal, über den die Ausgaben erfolgen. Wird bei CGI für das erzeugen der HTML-Dokumente benutzt.

URL-Codierung
Die einzelnen Formularelemente inklusive ihrer Daten werden durch ein kaufmännisches & voneinander getrennt. Name und Daten eines Formularelements werden durch ein Istgleich-Zeichen = voneinander getrennt. Leerzeichen in den eingegebenen Daten (z.B. bei mehreren Wörtern) werden durch ein Pluszeichen + ersetzt. Alle Zeichen mit den ASCII-Werten 128 bis 255 (hexadezimal 80 bis FF) werden durch eine Hexadezimalzeichenfolge umschrieben, eingeleitet durch ein Prozentzeichen % und dahinter der Hexadezimalwert des Zeichens (z.B. wird der deutsche Umlaut ö durch %F6 umschrieben). Alle Zeichen, die in diesen Regeln als Steuerzeichen vorkommen (also &, +, = und %) werden ebenfalls hexadezimal umschrieben, und zwar genau so wie höherwertige ASCII-Zeichen.


Bsp.:

Codierung:

AnwenderName=Stefan+M%FCnz&AnwenderMail=s.muenz@euromail.com&Text=Das+ist+ein+kleiner+Text

virtuelles Dokument
(HTML-) Dokument, das nicht statisch existiert; es wird von einem (CGI-) Programm flüchtig erzeugt, um direkt zum Benutzer geschickt zu werden.

II. Links

http://hoohoo.ncsa.uiuc.edu/cgi/overview.html
NCSA-Spezifikation des CGI-Standards

http://www.jmarshall.com/easy/cgi/german
einfache, leicht verständliche Einführung in CGI; Beispiele in Perl und C

http://www.teamone.de/selfhtml/tga.htm
umfassende Informationen zur Erstellung von eigenen Homepages + Einführung in CGI/Perl

http://userpage.fu-berlin.de/~ahahn/www/cgikurs/index.html
Einführungskurs in CGI mit Perl – Beispiel zur Programmierung eines Gästebuchs

http://schnellsuche3.de/suchmaschinen/perl_cgi/
Suchmaschine für CGI-/Perl-Skripts

http://www.perl-archiv.de/perl/index.shtml
Archiv von Perl-Skripts

http://www.zot.de/cgibillserver/
Archiv verschiedenster CGI-Skripts

http://www.cgi-service.de/
CGI-Host, bietet die Möglichkeit zum Betreiben eigener CGI-Programme

http://file.inf.bi.ruhr-uni-bochum.de/~danielk//cgi/cgitutor/cgitutor.html
CGI-Tutorial mit anschaulicher Erklärung

http://krum.rz.uni-mannheim.de/cgi-fol.html
Kurzübersicht mit Einleitung, Benutzung, Beispielen, Spezifikation

http://www.cs.uni-magdeburg.de/~reitz/cgi/tutorial.html
CGI-Tutorial, umfaßt Einführung Formularerstellung, enthält C-Code

http://www.activestate.com/
Download des ActiveState Perl 5.6 Interpreters

http://omnicron.ab.ca/
Download von OmniHTTPd (CGI-fähiger Web Server, frei verfügbar!)