SELFHTML: Perl / Perl-Module / Modul CGI: Funktionen für die CGI-Programmierung
Author: Redaktion SELFHTML, selfhtml81@selfhtml.org
Description: Wie sich das Perl-Standardmodul CGI für eigene CGI-Scripts verwenden lässt.
Keywords: SELFHTML, Perl, Module, Perlmodule, CGI, CGI-Modul
Date: 2005-11-09T00:29:27+01:00

| # Modul CGI: Funktionen für die CGI-Programmierung
| Allgemeines zum CGI-Modul CGI-Modul in Scripts einbinden Einfache (X)HTML-Ausgaben mit dem CGI-Modul Erweiterte Ausgaben mit dem CGI-Modul Formular-Verarbeitung mit dem CGI-Modul Umgebungsdaten ermitteln mit dem CGI-Modul Cookies verwalten mit dem CGI-Modul Automatische Umleitungen (Redirects) mit dem CGI-Modul Sicherheitseinstellungen mit dem CGI-Modul

## Allgemeines zum CGI-Modul

Das CGI-Modul gehört seit der Perl-Version 5.004 (Mai 1997) zu den Standardmodulen. Sie finden es meist im Verzeichnis /usr/lib/perl5/5.8.8 bzw. unter Windows in C:\Programme\Perl\lib unter dem Namen CGI.pm. Es fasst eine große Anzahl Funktionen zusammen, die typische Routine-Aufgaben von CGI-Scripts übernehmen. Eine relativ umfangreiche Erläuterung des Moduls können Sie sich auf der Konsole bzw. Eingabeaufforderung mit `perldoc CGI` ausgeben lassen. Seine Funktionen haben sich im Praxiseinsatz vielfach bewährt. Es ist deshalb sinnvoll, bei der Erstellung eigener CGI-Scripts auf die Ressourcen zurückzugreifen, die dieses Modul bereitstellt; man braucht dann nicht alles nochmals selbst zu schreiben.

Ein Nachteil des CGI-Moduls besteht allerdings darin, dass es recht groß ist. Das liegt (unter anderem) an seinem monolithischen Aufbau. Es übersetzt viel Code erst zur Laufzeit, wenn die Funktionen benötigt werden. Da darüber hinaus auch Cachingmechanismen auf dem Server dafür sorgen, dass die etwa 250 KB große Datei nicht bei jedem Aufruf neu eingelesen wird, sollten Sie nur bei kleinen CGI-Scripts wie etwa Zugriffszählern oder Weiterleitungen auf den Einsatz des CGI-Moduls verzichten. Bei den meisten CGI-Scripts ist seine Verwendung jedoch zu empfehlen, vor allem, wenn damit Formulardaten verarbeitet und (X)HTML-Dokumente zusammengestellt werden sollen. Denn das Modul übernimmt unter anderem auch eine ganze Reihe von automatischen Anpassungen an die Laufzeitumgebung des Scripts, wodurch mögliche Fehler vermieden bzw. minimiert werden können.

Das CGI-Modul besteht aus einem Hauptmodul und verschiedenen Untermodulen. Die Untermodule übernehmen im wesentlichen spezielle Aufgaben wie beispielsweise die Unterstützung des neueren Fast-CGI-Standards oder die Unterstützung so genannter Server-Pushs. In diesem Kapitel wird insbesondere dargestellt, wie Sie mit Hilfe des CGI-Moduls (X)HTML-Dokumente generieren und mit übermittelten Daten umgehen können. Das ist allerdings bei weitem nicht die einzige Aufgabe, die diesem Modul zugeteilt werden kann. Wenn Sie "nur" HTML ausgeben lassen möchten, könnten Sie sogar ganz auf das CGI-Modul verzichten; es gibt weitere Standardmodule, die für solche Aufgaben herangezogen werden könnten. Und schließlich ist Ihr Script auch dann, wenn es das CGI-Modul einsetzt, immer noch ein Perl-Script und kann neben dem Zusammenstellen von (X)HTML auch alle die anderen Dinge tun, für die Perl-Scripts nun einmal eingesetzt werden.

Und wie alles, was zu den Computersprachen gehört, unterliegt auch Perl einschließlich seiner Module einer stetigen Entwicklung. Manches, was Sie noch zum Erscheinungstermin von SELFHTML 8.1 (im November 2005) als gültig erläutert bekamen, ist bereits nach zwei Jahren nicht mehr im gleichen Maß gültig. Das hängt damit zusammen, dass auch das CGI-Modul beständig weiterentwickelt wird. Dazu vergleichen Sie bitte den aktuellen Entwicklungsstand im CPAN.

Im wesentlichen gibt es zwei Möglichkeiten, das CGI-Modul zu verwenden: eine objektorientierte und eine funktionsorientierte. Beide Konzepte haben ihre Vor- und Nachteile.

### Der funktionsorientierte Modus

Wenn Sie diesen Modus nutzen möchten, müssen Sie entweder eine oder mehrere bestimmte Funktion(en) in den Namensraum Ihres Scripts importieren - oder Sie importieren eine ganze Liste, die die von Ihnen gewünschten Methoden bereitstellt. Solche Funktionslisten beginnen grundsätzlich mit einem vorangestellten Doppelpunkt. Ein Beispiel, das ein vollständiges XHTML-Dokument erzeugt, könnte dann so ausssehen:

    #!/usr/bin/perl -w

    use CGI qw/:standard/;

    print header, start_html, p('Hallo Welt!'), end_html;

Es gibt mehrere Möglichkeiten, funktionsorientiert zu schreiben, auf die hier aber nicht näher eingegangen werden soll.

### Der objektorientierte Modus

Wenn Sie diesen Modus nutzen möchten, müssen Sie mindestens ein Objekt deklarieren, mit dem Sie die Funktionen des Moduls aufrufen können. Ihr Script beginnt dann grundsätzlich mit diesen Vorgaben (das ist noch kein vollständiges Script!):

    #!/usr/bin/perl -w

    use strict;
    use CGI;

    my $cgi = new CGI;

Der objektorientierte Modus gilt als eleganter und bietet mehr Möglichkeiten, wie etwa das Definieren mehrerer unabhängiger CGI-Objekte im gleichen Script. Deshalb beschränken sich die Beschreibungen und Scriptbeispiele dieses Kapitels auf die objektorientierte Verwendung des CGI-Moduls.

## CGI-Modul in Scripts einbinden

Das folgende Beispiel zeigt, wie Sie das CGI-Modul in ein eigenes Perl-Script einbinden und im objektorientierten Stil verwenden können.

### Beispiel eines vollständigen CGI-Scripts in Perl (1):

Anzeigebeispiel: So sieht's aus (Zum Aufruf des Scripts ist eine Internet-Verbindung erforderlich)

    #!/usr/bin/perl -w

    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;

    print $cgi->header('text/plain'), "Hallo Welt";

### Erläuterung:

Mit `use CGI` binden Sie das CGI-Modul in Ihr Script ein. Im Beispiel wird zusätzlich noch ein Untermodul namens `CGI::Carp` eingebunden, genauer, eine bestimmte Funktion daraus, nämlich die Funktion `fatalsToBrowser`. Beim Entwickeln von CGI-Scripts ist es immer sinnvoll, dies mit einzubinden. Diese Funktion hat zur Folge, dass alle Fehlermeldungen, die der Perl-Interpreter erzeugt, direkt im Browser ausgegeben werden. Und solange Sie in Ihrem Script noch Fehler (bugs) vermuten, ist es überaus nützlich, solche Fehlermeldungen unmittelbar im Browser zu sehen, statt sie sich mühsam aus dem Server-log herausfischen zu müssen. Es wird Ihnen damit beinahe so etwas wie ein Debugging-Modus zur Verfügung gestellt. Hat Ihr Script am Ende der Entwicklungsphase alle Tests fehlerfrei durchlaufen, können Sie diese Zeile auch wieder auskommentieren oder ganz und gar streichen. Im produktiven Einsatz hat sie keine Bedeutung mehr.

Nachdem das CGI-Modul eingebunden ist, wird mit `my $cgi = new CGI` eine neue Instanz des CGI-Objekts erzeugt. Mit dieser Anweisung sorgen Sie dafür, dass das CGI-Modul objektorientiert verwendet werden kann. Die Objektinstanz der CGI-Klasse ist nun über den Skalar `$cgi` ansprechbar. Im weiteren Verlauf des Scripts haben Sie über diesen Skalar Zugriff auf alle Funktionen, die das CGI-Modul bereitstellt. Bei objektorientierter Programmierung spricht man dann jedoch nicht mehr von Funktionen, sondern von Methoden.

Der Name des Skalars, der im Beispiel `$cgi` lautet, ist frei wählbar. Da Sie den Skalar im weiteren Verlauf des Scripts vermutlich sehr oft brauchen, empfiehlt sich ein kurzer Name. Viele Programmierer arbeiten mit einbuchstabigen Namen wie z.B. `$q`.

Das obige Beispiel gibt ein einfaches "Hallo Welt" aus. Wie immer muss zur Übergabe an einen aufrufenden Browser zuerst ein HTTP-Header erzeugt werden. Das CGI-Modul stellt dafür eine Funktion bzw. Methode namens `header()` zur Verfügung. Wenn dieser Methode kein Argument mitgegeben wird, erzeugt sie einen HTTP-Header für den MIME-Typ `text/html`, also für die Ausgabe von HTML-Code. Im obigen Beispiel soll jedoch unformatierter Text gesendet werden. Deshalb wird der Header nicht leer belassen, sondern ihm wird `text/plain` übergeben.

Am Beispiel des Aufrufs von `header()` können Sie sehen, wie der Zugriff über den zuvor definierten Skalar funktioniert. Nach dem Schema `$Skalar->Methode` "zeigen" Sie auf die Methode, und zwar mit dem Skalar, der an eine bestimmte zuvor erzeugte Instanz des CGI-Objekts gebunden wird.

Zum Senden des HTTP-Headers und des auszugebenden "Hallo Welt" wird im Beispiel die übliche print-Funktion von Perl verwendet. Diese Funktion kann ja mehrere durch Komma getrennte Argumente gleichzeitig ausgeben. Im Beispiel gibt sie zuerst den Rückgabewert der Methode `header()` aus, also den gewünschten HTTP-Header, und danach den Text `Hallo Welt`.

### Beispiel eines vollständigen CGI-Scripts in Perl (2):

    #!/usr/bin/perl -w

    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;

    print $cgi->header(),
          $cgi->start_html(),
          $cgi->h1('hallo Welt!'),
          $cgi->p('Solche sechs, wie wir fünf sind,
                   gibts keine vier mehr, wir drei sind die zwei einzigen ;-)'),
          $cgi->end_html();

### Erläuterung:

Wenn Sie die Methode `header()` so notieren, dass sie "leer" bleibt und der Skalar `$cgi` darauf "zeigt", wird der Perl-Interpreter im CGI-Modul diejenigen Festlegungen suchen, die es dafür enthält. Das ist in den aktuellen Versionen des CGI-Moduls für Perl 5.8.8 grundsätzlich XHTML 1.0, kann sich aber künftig zu XHTML 2.0 ändern. In diesem Fall bekommen Sie also zwingend den MIME-Typ text/html. Folglich müssen Sie außer dem HTTP-Header dafür sorgen, dass eine vollständige XHTML-Datei einschließlich `<head>` und `<body>` erzeugt werden kann. Das erreichen Sie mit `$cgi->start_html()`.

## Einfache (X)HTML-Ausgaben mit dem CGI-Modul

Das CGI-Modul stellt Ihnen eigene Methoden zur Verfügung, um (X)HTML-Code zusammenzustellen. Es können (mit wenigen Ausnahmen) für alle HTML-Elemente solche Methoden bereitgestellt werden. Die von HTML her gewohnten spitzen Klammern entfallen, aber allen Elementnamen werden runde Klammern nachgestellt, in denen Sie CSS-Angaben, EventHandler, diverse Attribute bzw. Parameter und natürlich auch den Text, der zuletzt ja im Browser angezeigt werden soll, notieren können. Gibt es nichts, was Sie unbedingt in solche runde Klammern schreiben möchten, können Sie sie auch weglassen.

### Beispiel eines vollständigen CGI-Scripts in Perl:

Anzeigebeispiel: So sieht's aus (Zum Aufruf des Scripts ist eine Internet-Verbindung erforderlich)

    #!/usr/bin/perl -w

    use strict;
    use CGI -no_xhtml;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;
    my $Autor = "der Reiseonkel";
    my $Ort = "Cap Ferret";

    print $cgi->header(),
          $cgi->start_html({-dtd => '-//W3C//DTD HTML 4.01 Transitional//EN',
                            -title => 'Reisebericht vom '.$Ort})."\n",
          $cgi->h1('Reisebericht vom '.$Ort)."\n",
          $cgi->p('Die größte Sanddüne Europas mit 117m
          Höhe sieht man bei klarem Wetter, wenn man am Ufer des Beckens von
          Arcachon steht. Das '.$Ort.' selbst ist ein kleiner Landzipfel, der
          vor allem aus Ferienhäusern besteht. Austernzucht, Fischerei und
          Wassersport prägen die Atmosphäre im Becken von Arcachon.')."\n",
          $cgi->hr({-noshade => undef, -size => '1'})."\n",
          $cgi->p({-style => 'color:red'}, "Autor: ", $cgi->em($Autor))."\n",
          $cgi->end_html();

### Erläuterung:

Zunächst wird das CGI-Modul wie bereits bekannt mit `use CGI` eingebunden, gleichzeitig sorgt der Parameter `-no_xhtml` dafür, dass vorerst gar keine Dokumenttyp-Festlegung erfolgt. Um das im objektorientierten Stil zu verwenden, wird dann mit `my $cgi = new CGI` eine neue Instanz des CGI-Objekts erzeugt. Es gibt aus Demonstrationsgründen noch zwei Variablen, die Ihnen zeigen sollen, dass Sie selbstverständlich auch in Ausgaben, die Sie mit dem CGI-Modul generieren, Variablen nutzen können.

Das Beispiel tut nichts anderes, als eine kleine vollständige HTML-Datei zusammenzustellen. Dazu wird zunächst mit `$cgi->header()` der HTTP-Header für HTML erzeugt. Dann folgt der HTML-Code. Der HTML-Code wird jedoch nicht wie bisher bekannt mit Hilfe der `print`-Funktion für einzelne HTML-Elemente geschrieben, sondern durch den Aufruf von Methoden, die das CGI-Modul bereitstellt, erzeugt. Grundsätzlich beginnt die HTML-Ausgabe mit der Methode `start_html()`, der Sie Parameter für diejenigen Elemente übergeben können, die Sie als Elemente des Headerbereichs kennen. Mit dem Parameter `dtd` müssen Sie beispielsweise den DTD-Bezeichner festlegen, um das ausgegebene Dokument standardkonform gestalten zu können, falls Sie oben den `-no_xhtml`-Parameter verwendet haben. Die Methode `start_html()` kann alle Elemente des Header-Bereichs einer HTML-Datei zur Verfügung stellen, sowie ein öffnendes `<body>`-tag.

Für alle gängigen HTML-Elemente und HTML-Tags, die Sie innerhalb von `<body>` verwenden möchten, gibt es solche Methoden. Dabei können Sie entweder das komplette HTML-Element erzeugen, oder auch nur ein Start- oder End-Tag. Die Anweisung `$cgi->h1('Reisebericht vom '.$Ort)` erzeugt beispielsweise ein komplettes HTML-Element mitsamt Inhalt - und zugleich sehen Sie, dass Sie dort auch Variablen einsetzen können, wie Sie es von Perl ja gewohnt sind. Der erzeugte Code lautet `<h1>Reisebericht vom Cap Ferret</h1>`. Auf die gleiche Weise funktioniert es mit den anderen HTML-Elementen. `$cgi->strong('wichtiger Text')` würde beispielsweise den HTML-Code `<strong>wichtiger Text</strong>` erzeugen. Die Überschrift im Beispiel könnte aber auch folgendermaßen notiert werden:
`$cgi->start_h1(),'Reisebericht vom '.$Ort,$cgi->end_h1()`.
Neben den kompletten Element-Methoden gibt es also auch Methoden, die nur ein einleitendes oder schließendes HTML-Tag erzeugen. `$cgi->start_h1()` erzeugt nur den HTML-Code `<h1>`, und `$cgi->end_h1()` den Code `</h1>`. Entsprechende Methoden gibt es für alle Elemente, also beispielsweise auch `$cgi->start_strong()` und `$cgi->end_strong()`.

Die Verwendung solcher Methoden für öffnende und schließende Tags ist dann sinnvoll, wenn die Tags weit auseinanderliegen und sehr viel Inhalt haben. Vor allem bei `<html>...</html>` ist das natürlich der Fall, dazwischen steht ja der komplette anzuzeigende Inhalt Ihrer Datei. Die Methode `$cgi->start_html()`, die auch im obigen Beispiel verwendet wird, hat jedoch eine Sonderstellung. Sie erzeugt nicht nur ein einleitendes `<html>`-Tag, sondern schreibt auch den Standard-Dateikopf der HTML-Datei mit den Elementen `head` und `title` sowie einem öffnenden `<body>`.

Viele einleitende HTML-Tags haben Attribute. Um diese vom Inhalt des Elements zu unterscheiden, bieten die Methoden eine besondere Syntax an. Am obigen Beispiel ist das etwa an der Trennlinie erkennbar. Mit der Anweisung: `$cgi->hr({-noshade => undef, -size => '1'})` wird der HTML-Code `<hr noshade size="1">` erzeugt. Das Argument, das der Methode übergeben wird, muss dazu in geschweiften Klammern `{` bzw. `}` stehen. Jedes Attribut wird durch ein Minuszeichen `-` eingeleitet. Wertzuweisungen an Attribute werden durch den Operator `=>` vom Attribut getrennt. Mehrere Attribute werden wie im `hr`-Beispiel innerhalb der geschweiften Klammern durch Kommata getrennt.

Die Methoden zum Erzeugen von HTML-Elementen können auch mehrere Argumente übergeben bekommen. Dabei müssen Sie die Argumente durch Kommata trennen. Ein komplexeres Beispiel sehen Sie an der letzten `$cgi->p(...)`-Anweisung. Dieser Methodenaufruf übergibt drei Argumente. Das erste Argument ist ein Attribut für das einleitende `<p>`-Tag, nämlich ein `style`-Attribut, in dem die Schriftfarbe rot bestimmt wird. Das zweite Argument ist statischer Text, und das dritte Argument zeigt gleich zwei weitere Möglichkeiten: es enthält einen weiteren Aufruf einer Element-Methode, nämlich `$cgi->i()` für kursiven Text. Und als Argument wird dieser Methode kein statischer Text übergeben, sondern ein Skalar namens `$Autor`, der weiter oben im Beispiel definiert wird.

Die Argumente erlauben also das bequeme Verschachteln von HTML-Elementen, ebenso wie das Einfügen von variablen Inhalten, die zuvor vom Script ermittelt wurden.

### Beachten Sie:

Das Einbinden des CGI-Moduls zwingt Sie keinesfalls dazu, HTML-Code auf diese Weise zu erzeugen. Sie können die HTML-Ausgaben auch direkt mit der `print`-Funktion erzeugen oder zuvor eingelesene Templates ausgeben. Sie können auch Methodenaufrufe des CGI-Moduls mit herkömmlicher HTML-Code-Erzeugung mischen. Es ist also kein Problem, Mischformen wie diese zu notieren:
`print "<hr noshade size='1'>",
$cgi->p({-style => 'color:red'}, "Autor: <i>$Autor</i>");`

Normalerweise werden alle HTML-Elementnamen innerhalb der Methoden klein geschrieben, also z.B. `start_div()`, `end_div()` oder `div()`. Es gibt jedoch ein paar Ausnahmen, um Kollisionen mit gleichnamigen Sprachbestandteilen von Perl zu vermeiden. Die HTML-Elemente `Tr`, `Select`, `Link` und `Sub` beginnen mit Großbuchstaben, also etwa in einer Anweisung wie `$cgi->Sub('tiefgestellter Text')`.

HTML-Kommentare können Sie mit der Methode `comment()` setzen. So erzeugt die Anweisung `$cgi->comment('derzeit nicht aktuell')` den HTML-Code `<!-- derzeit nicht aktuell -->`.

## Erweiterte Ausgaben mit dem CGI-Modul

HTTP-Header können manchmal Zusatzinformationen enthalten, die für die Client-Server-Kommunikation von Bedeutung sind. Und was den HTML-Dateikopf betrifft, so kann dieser ebenfalls wichtige allgemeine Angaben zur HTML-Datei enthalten, z.B. Meta-Tags, Scriptbereiche für CSS oder Javascript, logische Beziehungen oder Attribute zur Seitengestaltung im einleitenden `<body>`-Tag (die zwar zulässig und noch nicht einmal "deprecated" sind, trotzdem aber besser mit CSS bestimmt werden sollten).

### Beispiel eines vollständigen CGI-Scripts in Perl:

Anzeigebeispiel: So sieht's aus (Zum Aufruf des Scripts ist eine Internet-Verbindung erforderlich)

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;

    print $cgi->header(-type    =>'text/html',
                       -expires =>'+1h'),
          $cgi->start_html(-title  =>'Testseite mit Link',
                           -author =>'beispiel@example.org',
                           -base   =>'true',
                           -target =>'_blank',
                           -meta   =>{'keywords'   =>'TeamOne, Test',
                                      'description'=>'ein kleiner Test mit einem Link'},
                           -style  =>{'src'=>'/styles/formate.css'},
                           -BGCOLOR=>'#FFFFCC',
                           -TEXT   =>'#000000',
                           -LINK   =>'red',
                           -VLINK  =>'blue',
                           -ALINK  =>'black'),
          $cgi->p('ein kleiner Test mit einem ',
                  $cgi->a({-href => 'http://www.selfhtml.org/'},'Link auf selfhtml.org')),
          $cgi->end_html();

### Erläuterung:

Das Script bindet mit `use CGI` das CGI-Modul ein. Da kein Parameter zur Modifizierung der Dokumenttyp-Deklaration angegeben ist, wird standardmäßig XHTML 1.0 generiert werden. Das Script erzeugt dann mit `my $cgi = new CGI` eine neue Instanz des CGI-Objekts. Bei der HTML-Ausgabe, die es anschließend zusammenstellt, nutzt es verschiedene Möglichkeiten, um den HTTP-Header und die Daten im Kopf der HTML-Datei zu beeinflussen.

Sowohl der Methode `header()` zum Erzeugen des HTTP-Headers als auch der Methode `start_html()` zum Erzeugen des HTML-Dateikopfes können Sie mehrere Argumente übergeben. Beide Methoden kennen jeweils ein Standardargument: bei `header()` ist dies der MIME-Typ, und bei `start_html()` der Inhalt des `title`-Elements. Deshalb können Sie diese Argumente ohne weiteres direkt angeben, also etwa in der Form `header('text/plain')` oder `start_html('Text des Titels')`. Bei Angabe von mehreren und weiteren Argumenten sollten Sie jedoch die oben gezeigte Syntax verwenden. Dabei besteht jedes Argument aus einem Parameternamen, eingeleitet durch ein Minuszeichen `-`, einem Zeigeoperator `=>` und dem gewünschten Wert.

### Argumente beim HTTP-Header

Die folgende Tabelle zeigt Ihnen, welche Angaben zum HTTP-Header Sie notieren können. Die Code-Beispiele der linken Spalte stellen nur den reinen Methodenaufruf von `header()` dar.

Aufrufbeispiel | Erläuterung
--- | ---
`header(-type=>'image/gif');` | Mit `-type` können Sie den MIME-Typ des nachfolgenden Datenstroms bestimmen. Im Beispiel können Sie anschließend die binären Daten einer GIF-Grafik ausgeben (dazu vorher gegebenenfalls die Funktion binmode aufrufen!)
`header(-status=>'204 No response');` | Mit `-status` können Sie eine HTTP-Statusmeldung an den Browser senden. Mit der Beispielanweisung (HTTP-Status 204) können Sie die Ausgabe weiterer Daten an den Browser verweigern. Beim Anwender bleibt die zuletzt angezeigte Seite am Bildschirm stehen. Sinnvoll beispielsweise, wenn der Anwender durch Klick auf einen Link ein Voting-Script anstößt, das ihn aber nicht am sofortigen Weiterlesen der Seite hindern soll.
`print $cgi->header(-expires=>'+120s');` | Mit `-expires` können Sie bewirken, dass der Browser die HTML-Ausgabe für einen Mindestzeitraum in seinen Cache-Speicher übernimmt. Bei einem Reload der ausgegebenen Seite innerhalb des angegebenen Zeitraums ruft der Browser dann nicht mehr das Script auf, sondern holt den HTML-Code aus seinem Cache. Den Zeitraum geben Sie als Zahl mit voranstehendem Pluszeichen und einem nachgestellten Buchstaben für die Zeiteinheit an. Die Angabe `'+30s'` im Beispiel bedeutet "HTML-Code 30 Sekunden im Cache halten". Andere Zeiteinheiten sind `m` (Minuten), `h` (Stunden), `d` (Tage), `M` (Monate) und `y` (Jahr). Darüber hinaus sind absolute Zeitangaben im UTC-Format erlaubt, wie z.B. `Friday, 08-Jun-2001 11:29:00 GMT+0100`.
`print $cgi->header(-cookie=>$Cookie);` | Mit `-cookie` können Sie einen Cookie aktivieren. Mehr dazu im Abschnitt Cookies verwalten mit dem CGI-Modul.
`print $cgi->header(-nph=>1);` | Mit diesem Befehl können Sie so genannte NPH-Scripts schreiben. NPH steht für no-parsed-header und bedeutet, dass das CGI-Script die nachfolgenden Daten direkt an den aufrufenden Browser sendet, ohne dass der Webserver etwas davon mitbekommt. Dies kann zu Performance-Gewinnen führen, und in einigen Fällen, etwa beim Einsatz des Microsoft IIS-Webservers, ist es sogar vorgeschrieben, den NPH-Modus zu verwenden.

### Dokumenttyp-Deklarationen (DTD)

Standardmäßig verwendet das CGI-Modul, wie bereits angedeutet, XHMTL 1.0 Transitional. Das heißt, Sie finden eine Dokumenttyp-Angabe im generierten XHTML-Dokument grundsätzlich in dieser Form vor:

    <!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">

Nun kann es aber durchaus Gründe geben, weshalb Sie eine andere DTD einsetzen möchten - beispielsweise möchten Sie vielleicht ein Frameset erzeugen oder müssen auf HTML 4.01 bestehen. Dann können Sie das CGI-Modul dazu zwingen, gar keine Vorgabe zu machen, indem Sie es in der Form `use CGI -no_xhtml;` in Ihr Script einbinden. Das bedeutet zugleich, dass Sie dann an anderer Stelle eine entsprechende Deklaration vornehmen müssen. Dazu stellt Ihnen das CGI-Modul für die Methode `$cgi->start_html()` den Parameter `-dtd` zur Verfügung, den Sie in dieser Form notieren können:

    $cgi->start_html(-dtd > '-//W3C//DTD HTML 4.01 Strict//EN');

Die folgende Liste enthält einige Documenttyp-Deklarationen, die Sie bei Bedarf wählen können:

- '-//W3C//DTD HTML 4.01//EN'
- '-//W3C//DTD HTML 4.01 Transitional//EN'
- '-//W3C//DTD HTML 4.01 Frameset//EN'
- '-//W3C//DTD XHTML 1.0 Strict//EN'
- '-//W3C//DTD XHTML 1.0 Transitional//EN'
- '-//W3C//DTD XHTML 1.0 Frameset//EN'
- '-//W3C//DTD XHTML 1.1//EN'
- '-//W3C//DTD HTML 3.2//EN'
- '-//W3C//DTD HTML 2.0//EN'

Sie sehen, dass Sie nicht die gesamte (dreizeilige) Deklaration notieren müssen. Das CGI-Modul ergänzt die fehlenden Angaben, so dass in Ihrer vom Script generierten HTML-Ausgabe immer die vollständige Dokumenttyp-Deklaration zu finden sein wird. Denken Sie daran, dass von der Wahl der für Ihr Seitenprojekt zutreffenden DTD unter anderem abhängt, welche HTML-Elemente Sie überhaupt verwenden dürfen und wie sie auszusehen haben, um validen HTML-Code zu generieren.

### Argumente beim HTML-Dateikopf

Die folgende Tabelle listet auf, welche Angaben Sie zum HTML-Dateikopf notieren können. Die Code-Beispiele der linken Spalte stellen nur den reinen Methodenaufruf von `start_html()` dar.

Aufrufbeispiel | Erläuterung
--- | ---
`start_html(-title=>'Titeltext');` | Mit `-title` bestimmen Sie den Titel der HTML-Ausgabe. Das Beispiel erzeugt den folgenden HTML-Code: `<TITLE>Titeltext</TITLE>`
`start_html(-author=>'beispiel@example.org');` | Mit `-author` erzeugen Sie eine logische Beziehung zu einer E-Mail-Adresse. Das Beispiel erzeugt folgenden HTML-Code: `<LINK REV=MADE HREF="mailto:beispiel%40example.org">`
`start_html(-base=>'http://example.org/');` | Mit `-base` bestimmen Sie die Basisadresse der ausgegebenen HTML-Seite. Das Beispiel erzeugt folgenden HTML-Code: `<BASE HREF="http://example.org/">`
`start_html(-target=>'dataframe');` | Mit `-target` bestimmen Sie den Basis-Fensternamen für Links in der HTML-Ausgabe. Das Beispiel erzeugt folgenden HTML-Code: `<BASE TARGET="dataframe">`
`start_html(-meta=>{'keywords'=>'HTML,CSS'});` | Mit `-meta` können Sie Meta-Angaben notieren - jedoch nur solche, die in HTML vom Typ `name` sind, nicht solche, die vom Typ `http-equiv` sind. Mehrere Meta-Angaben gleichzeitig sind erlaubt. Jede einzelne Meta-Angabe muss in geschweiften Klammern stehen. Innerhalb der geschweiften Klammern folgt zunächst der Wert, der in HTML dem `name`-Attribut zugewiesen würde, gefolgt von dem Operator `=>` und dem Wert, den Sie in HTML dem `content`-Attribut zuweisen würden. Das Beispiel erzeugt folgenden HTML-Code: `<META NAME="keywords" CONTENT="HTML,CSS">`
`start_html(-BGCOLOR=>'#000000');` | Mit allen anderen Argumenten, die mit einem Minuszeichen beginnen und keinen der anderen reservierten Namen wie `-title` oder `-meta` haben, bestimmen Sie Attribute, die ins einleitende `<body>`-Tag eingefügt werden. Das Beispiel erzeugt folgenden HTML-Code: `<BODY BGCOLOR="#000000">`

## Formularverarbeitung mit dem CGI-Modul

In der Regel werden CGI-Scripts von HTML-Formularen über das `action`-Attribut innerhalb des Formulars aufgerufen (es gibt auch andere Möglichkeiten, beispielsweise über SSI). Typischerweise sieht ein HTML-Formular so ähnlich aus wie im folgenden Beispiel.

### Beispiel: HTML-Datei mit CGI-Aufruf

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <title>Kommentarseite</title>
    <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
    <h1>Ihr Kommentar</h1>
    <form action="/cgi-bin/comments.pl" method="post">
    <p>Name:<br><input size="40" maxlength="40" name="AnwenderName"></p>
    <p>Text:<br><textarea rows="5" cols="50" name="Kommentartext"></textarea></p>
    <p><input type="submit" value="Absenden"></p>
    </form>
    </body>
    </html>

### Beispiel: vollständiges CGI-Script (comments.pl) mit HTML-Ausgabe

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;
    my @Feldnamen = $cgi->param();

    print $cgi->header(),
          $cgi->start_html('CGI-Feedback'),
          $cgi->h1('CGI-Feedback vom Programm ',$cgi->i('comments.pl'));
          foreach my $Feld (@Feldnamen) {
            print $cgi->strong('Feldname: '),
                  $Feld,
                  $cgi->strong(', Inhalt: '),
                  $cgi->param($Feld), "<br>";
          }
    print $cgi->end_html();

### Erläuterung:

Sobald Sie den "submit"-button dieses Formulars mit der Maus anklicken, wird Ihr Browser angewiesen, sich erneut an den Webserver mit einer Anfrage zu wenden. Die Art dieser Anfrage bestimmt das Attribut `method`, dessen Wert in den meisten Fällen `post` lauten wird. Mit dem Attribut `action` informiert das Formular den Webserver, was er tun soll - es muß ja nicht unbedingt ein Perl-Script sein, das der Server um Übernahme und Weiterverarbeitung der von Ihnen eingegebenen und vom Browser ebenfalls übermittelten Daten bitten soll. Auch ein PHP-Script, ein Shell-Script, eine ausführbare Datei (*.exe), eine Stapelverarbeitungsdatei (*.bat) oder ein anderer Programmaufruf kann von `action` initialisiert werden. In diesem Fall ist es jedoch das Perl-Script `comments.pl`, das einfach die übergebenen Daten sortiert, auswertet und als HTML wieder zurückliefert.

Die Bezeichnung "Formularverarbeitung" ist zwar üblich, aber streng genommen nicht ganz korrekt. Es ist ja keineswegs das Formular, das verarbeitet wird, sondern es handelt sich um diejenigen Daten, die Sie in bestimmte Eingabefelder eingetragen haben: Namen, Adressen, Texte usw. Entsprechend der im Formular angegebenen Übermittlungsmethode (`POST` oder `GET`, andere HTTP-Zugriffsmethoden wie `PUT` oder `DELETE` spielen hier keine Rolle) schickt der Browser nach Aktivierung eines "submit"-buttons oder nach dem Drücken der Enter-Taste einen Datenstrom an den Webserver. Der Webserver entscheidet, was er damit machen soll und schickt alles an den Perl-Interpreter, der wiederum das CGI-Modul fragt, wie er den ganzen Datenstrom auftrennen und in sinnvolle Einzelinformationen umwandeln soll. Das CGI-Modul stellt ihm dafür die Methode `param()` zur Verfügung. Mit dieser Methode werden, falls vorhanden, die Teile des übermittelten Datenstroms als Array gespeichert. Und diesen Array kann Ihr Script nun beliebig verwenden.

### Die Methode `param()`

Bei der Methode `param` kommt es darauf an, in welchem Kontext sie aufgerufen wird. Dementsprechend unterschiedlich ist ihr Rückgabewert. Sie können zum Beispiel ein Array `@Feldnamen = $cgi->param()` notieren. Es handelt sich dann also um einen Listenkontext, d.h. erwartet wird eine Liste als Rückgabewert. Bei dieser Art des Aufrufs liefert `param()` sämtliche Feldnamen eines eingelesenen Formulars zurück. Das sind jene Namen, die im HTML-Formular bei der Definition der Formularfelder jeweils mit dem Attribut `name` festgelegt wurden. Wenn `param()` ein einzelner Feldname als Parameter übergeben wird, liefert die Methode den zugehörigen Wert oder Inhalt des Feldes zurück. Der Kontext ist dann skalar.

Die folgende Tabelle fasst die Aufrufmöglichkeiten von `param()` zusammen.

Aufrufbeispiel | Rückgabewert | Erläuterung
--- | --- | ---
`if($cgi->param())` | Liste, im booleschen Kontext ausgewertet (`true` oder `false`) | Ein solcher Aufruf in Form einer `if`-Bedingung ermittelt, ob überhaupt Daten an das Formular übergeben wurden oder nicht. Dies ist sinnvoll, wenn ein Script aus mehreren verschiedenen Kontexten heraus aufgerufen werden kann und erst einmal feststellen muss, ob es Formulardaten erhalten hat oder nicht. Im `if`-Zweig könnten die Formulardaten eingelesen werden, und im `else`-Zweig könnten Anweisungen stehen für den Fall, dass keine Formulardaten übergeben wurden.
`$Wert = $cgi->param('AnwenderName')` | Skalar | Gibt den Wert oder Inhalt des Formularfeldes mit dem Namen `AnwenderName` zurück. Diese Form der Notation ist sinnvoll, wenn Sie als Script-Autor die Feldnamen übergebener Formulardaten kennen und direkt den Wert oder Inhalt des jeweiligen Feldes ermitteln möchten.
`@Namen = $cgi->param()` | Liste | Gibt sämtliche Feldnamen des Formulars zurück. |
`$cgi->param($Namen[2])` | Skalar | Gibt den Wert oder Inhalt des dritten Formularfeldes zurück (`$Namen[0]` wäre das erste Formularfeld), sofern zuvor mit `@Namen = $cgi->param()` die Feldnamen als Liste gespeichert wurden.
`@Zutaten = $cgi->param('Zutat')` | Liste | Gibt den Wert oder Inhalt einer Formularfeldgruppe mit gleichen Namen zurück zurück - vor allem bei Checkboxen in HTML-Formularen ist diese Aufrufvariante wichtig. In der Liste `@Zutaten` stehen anschließend alle Zutaten, die ein Anwender in Checkbox-Elementen mit dem Attribut `name="Zutat"` angekreuzt hat.

### Beachten Sie:

Die Darstellung der Methode `param()` ist ein hervorragend geeignetes Beispiel, um Ihnen etwas detaillierter zu zeigen, was das CGI-Modul für Sie erledigt. In vielen älteren Perl-Scripts, die Sie im Internet finden können (und auch in älteren Versionen dieser SELFHTML-Seite, die Sie sich im Archiv anschauen können), sehen Sie beispielsweise solche kryptisch wirkende Anweisungen:

    if($ENV{'REQUEST_METHOD'} eq 'GET') {
      $Daten = $ENV{'QUERY_STRING'}
    }
    else {
      read(STDIN, $Daten, $ENV{'CONTENT_LENGTH'});
    }
    sub verarbeiten {
    @Formularfelder = split(/&/, $Daten);
    foreach $Feld (@Formularfelder) {
      ($name, $value) = split(/=/, $Feld);
      $value =~ tr/+/ /;
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
      $Formular[$i] = $name;
      $i = $i + 1;
      $Formular[$i] = $value;
      $i = $i + 1;
     }
    }

Solche Anweisungen müßten Sie, wenn Sie Formulardaten verarbeiten möchten, erneut in Ihrem Script notieren, wenn Sie auf das CGI-Modul verzichten wollten. Das CGI-Modul nimmt Ihnen nun diese Arbeit ab, da es (in geringfügig anderer Form) genau diese Anweisungen bereits enthält und dem Perl-Interpreter deren Ergebnisse in einer Form zur Verfügung stellt, die es Ihnen wiederum erlaubt, sie einfach mit der Benutzung der Methode `param()` abzurufen. Beispielsweise könnten Sie so etwas in Ihrem Script notieren:

    print $cgi->p('Ihr Name ist: '.$cgi->param('AnwenderName'));

Damit würde die Methode `param()` im skalaren Kontext aufgerufen und der im oben schematisch dargestellten HTML-Formular eingetragene Name des Formularbenutzers ausgegeben. Im oben dargestellten Beispielscript `comments.pl` wird die Methode `param()` allerdings im Listenkontext verwendet, daher müssen Sie in diesem Script die Array-Bestandteile erst mit einer foreach-Schleife "individualisieren", um sie ausgeben zu können. Ein solcher Listenkontext ist dann nützlich, wenn das Script von unterschiedlichen Formularen verwendet wird, die unterschiedlich viele Eingabefelder mit unterschiedlichen Namen enthalten. In einem solchen Fall weiß das Script (bzw. wissen Sie als Programmierer) nicht von vornherein, welche Daten im Datenstrom enthalten sind und als HTML zurückgeliefert werden sollen; `$cgi->param('AnwenderName')` könnte auch leer (nicht existent) sein und es könnten andere `name`-Attribute mit Werten belegt worden sein. Wenn Sie `param()` im Listenkontext verwenden, vermeiden Sie mögliche Fehler.

### Formularerstellung

Wenn Sie sich intensiver mit Perl beschäftigen und das CGI-Modul ausgiebig nutzen, werden Sie vermutlich kein statisches HTML-Dokument zum Aufruf einer Formularauswertung einsetzen, sondern dieses Formular auch gleich selbst von Ihrem Script generieren lassen. Das hat verschiedene Vorteile: Sie können beispielsweise in Abhängigkeit von Umgebungsdaten Umgebungsdaten, die Sie zuvor ermitteln, Formularfelder mit Werten vorbelegen. Ausserdem füllt das CGI Modul diese Felder automatisch, wenn Sie das Formular, z.b. nach einer Fehleingabe, wieder mit den eingegebenen Werten ausgefüllt anzeigen lassen wollen (dieses Verhalten ist manchmal nicht erwünscht und kann bei Bedarf durch den Parameter `-override => 1` unterdrückt werden).

### Beispiel eines vollständigen CGI-Scripts in Perl

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;

    print $cgi->header();
    if ($cgi->param('absenden')) {
       print $cgi->start_html(-title=>'Auswertung');
       anzeige($cgi);
    } else {
       print $cgi->start_html(-title=>'Testformular');
       formular($cgi);
    }
    print $cgi->end_html();

    sub formular{
        print $cgi->start_form().
              $cgi->table({-border => 1},
                 $cgi->Tr([
                    $cgi->td([
                       $cgi->strong('Name : ').
                       $cgi->textfield(-name =>'name', -size => 40)
                    ]),
                    $cgi->td([
                       'E-Mail : '.
                       $cgi->textfield(-name =>'mail', -size => 40)
                    ]),
                    $cgi->td([
                       $cgi->strong('Text : ').
                       $cgi->textarea({-name =>'text', -columns =>50, -rows =>5})
                    ]),
                    $cgi->td([
                       $cgi->submit(-name => 'absenden', -value =>'absenden').
                       $cgi->reset(-value =>'verwerfen')
                    ])
                 ])
               ).
              $cgi->end_form();
    }

    sub anzeige{
        print $cgi->h2('hier kommt die Auswertung');

          if (!$cgi->param('name') && !$cgi->param('text')) {
             print $cgi->strong(q~Sie haben nichts eingegeben.
             Bitte wiederholen Sie Ihre Eingabe~);
             return formular($cgi);
          }
          if ($cgi->param('name')) {
             print $cgi->strong('Ihr Name ist: '.$cgi->param('name')),
             $cgi->br;
          }
          if ($cgi->param('mail')) {
             print $cgi->strong('Ihre mail ist: '.$cgi->param('mail')),
             $cgi->br;
          }
          if ($cgi->param('text')) {
             print $cgi->strong('Ihre Nachricht: ' .$cgi->param('text')),
             $cgi->br;
          }
    }

### Erläuterung:

Wie immer in den hier vorgestellten Beispielen wird zunächst das CGI-Modul eingebunden und danach mit `my $cgi = new CGI` eine neue Instanz des CGI-Objekts erzeugt. Es folgt jedoch nicht unmittelbar die Ausgabe von HTML-Code, sondern eine bedingte Anweisung. Das Script entscheidet anhand eventuell vorhandener `POST-Variablen`, welche der beiden Subroutinen es abarbeiten soll. Findet es keine `POST-Variable` mit dem Wert "absenden" (auch der "submit"-button sendet einen Wert für eine `POST-Variable`), so ruft es die Subroutine "anzeige" auf, die ein vollständiges HTML-Formular zur Verfügung stellt. Wurde dieses Formular bereits ausgefüllt, existieren aber `POST-Variablen`, also befolgt das Script dann die Festlegungen der ersten Subroutine und liefert dem Webserver Angaben zur Darstellung der eingegebenen Werte zurück.

### Beachten Sie:

Für das Script wird der objektorientierte Modus verwendet. Bisher haben Sie an den vorgestellen Scriptbeispielen gesehen, dass HTML-Elemente in diesem Modus von Methoden eines CGI-Objekts dargestellt werden. Aber auch Subroutinen sind in diesem Modus nichts anderes als Objektmethoden. Sie erkennen es an der Art, in der die im Script enthaltene bedingte Anweisung entscheidet, welche Subroutine aufgerufen werden soll: `formular($cgi);`.

## Umgebungsdaten ermitteln mit dem CGI-Modul

Häufig benötigt ein CGI-Script Informationen über seine Umgebung, z.B. über den Server, den aufrufenden Browser, oder über seinen eigenen Speicherort auf dem Server. Das CGI-Modul stellt zum Ermitteln solcher Daten verschiedene Methoden bereit.

### Beispiel eines vollständigen CGI-Scripts in Perl:

Anzeigebeispiel: So sieht's aus (Zum Aufruf des Scripts ist eine Internet-Verbindung erforderlich)

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;

    print $cgi->header(),
          $cgi->start_html('Umgebungsdaten'),
          $cgi->start_table({-border => '1'}),
            $cgi->Tr($cgi->th({-align => 'right'},'Script-URI:'),
                     $cgi->td($cgi->url(-full => 1))),
            $cgi->Tr($cgi->th({-align => 'right'},'relative Script-URI:'),
                     $cgi->td($cgi->url(-relative => 1))),
            $cgi->Tr($cgi->th({-align => 'right'},'Server-Software:'),
                     $cgi->td($cgi->server_software())),
            $cgi->Tr($cgi->th({-align => 'right'},'Browser-Software:'),
                     $cgi->td($cgi->user_agent())),
          $cgi->end_table(),
          $cgi->end_html();

### Erläuterung:

Das Beispielscript bindet zunächst mit `use CGI` das CGI-Modul ein und erzeugt mit `my $cgi = new CGI` eine neue Instanz des CGI-Objekts. Anschließend gibt es HTML-Code zur Übermittlung an den aufrufenden Browser aus, hier ist es eine Tabelle mit ein paar Umgebungsinformationen. Die HTML-Ausgaben werden mit Hilfe der Methoden des CGI-Moduls und deren Regeln realisiert. Die ausgegebene Tabelle listet in der linken Spalte in einem `th`-Element jeweils auf, welche Information die Zeile enthält, und in der rechten Spalte in einem `td`-Element den zugehörigen Wert. Dieser Wert wird jeweils mit Methoden des CGI-Moduls ermittelt. So wird mit `$cgi->url(-full => 1)` beispielsweise der URI des Scripts ermittelt.

Die folgende Tabelle listet verfügbare Methoden für Umgebungsdaten auf. Die Aufrufbeispiele gehen davon aus, dass mit `my $cgi = new CGI` eine Instanz des CGI-Objekts erzeugt wurde. Die Tabelle ist nach Methodennamen alphabetisch sortiert.

Methode | Rückgabewert | Erläuterung
--- | --- | ---
`$cgi->Accept()` | Liste | Ermittelt eine Liste der MIME-Typen, die der aufrufende Browser akzeptiert. Dies ist interessant abzuprüfen, bevor ein Script Daten eines nicht selbstverständlichen MIME-Typs an den Browser senden will. Es kann sein, dass die Liste nur aus einem Element mit dem Wert `*/*` besteht. Dann akzeptiert der aufrufende Browser potentiell alle MIME-Typen.
`$cgi->auth_type()` | Skalar | Ermittelt den Typ der Benutzer-Authentifizierung, sofern das Script zugangsgeschützt und nur durch Eingabe entsprechender Zugangsdaten aufrufbar ist.
`$cgi->path_info()` | Skalar | Ermittelt zusätzliche, wie weitere Unterverzeichnisse notierte Angaben. Wenn das Script beispielsweise die Adresse `http://meine.seite.net/cgi-bin/test.pl` hat, aber mit `http://meine.seite.net/cgi-bin/test.pl/querys/musicbase.sql` aufgerufen wird, dann ermittelt dieser Befehl den Anteil `/querys/musicbase.sql`. Beachten Sie, dass Aufrufe dieser Art nicht von allen Webservern korrekt verarbeitet werden.
`$cgi->path_translated()` | Skalar | Ermittelt wie `$cgi->path_info()` zusätzliche, wie weitere Unterverzeichnisse notierte Angaben, jedoch mit dem Unterschied, dass nicht der Anteil aus dem URI zurückgegeben wird, sondern der vom Webserver übersetzte Datenpfad dieses Anteils. Angenommen, das Script hat die Adresse `http://meine.seite.net/cgi-bin/test.pl`, wurde aber mit `http://meine.seite.net/cgi-bin/test.pl/querys/musicbase.sql` aufgerufen. Dann könnte der zusätzliche Adressanteil `/querys/musicbase.sql` aus Sicht des Webservers beispielsweise in einen physikalischen Pfadnamen wie `/usr/web/seite/querys/musicbase.sql` aufgelöst werden. Diesen Pfadnamen würde `$cgi->path_translated()` zurückgeben.
`$cgi->referer()` | Skalar | Ermittelt den URI der im Browser angezeigten Seite, von der aus das CGI-Script aufgerufen wurde. Ein solcher Wert lässt sich dann ermitteln, wenn das Script über ein abgesendetes Formular oder über einen Link aufgerufen wurde.
`$cgi->remote_host()` | Skalar | Ermittelt den Internetzugangs-Domainnamen (falls verfügbar) oder die Zugangs-IP-Adresse des aufrufenden Browsers.
`$cgi->remote_user()` | Skalar | Ermittelt den Benutzernamen, mit dem sich der aufrufende Benutzer angemeldet hat, um das CGI-Script aufzurufen. Wenn das Script beispielsweise htaccess-geschützt ist, muss sich der aufrufende Benutzer mit Benutzernamen und Passwort anmelden. Der dabei eingegebene Benutzername kann mit diesem Befehl ermittelt werden.
`$cgi->request_method()` | Skalar | Ermittelt die HTTP-Methode, mit der das CGI-Script aufgerufen wurde, gibt also üblicherweise `GET` oder `POST` zurück.
`$cgi->script_name()` | Skalar | Ermittelt den absoluten HTTP-Pfad des CGI-Scripts. Bei einem Script mit der Adresse `http://meine.seite.net/cgi-bin/test.pl` würde also `/cgi-bin/test.pl` ermittelt. Dieser Wert eignet sich sehr gut für weitere Selbstaufrufe des Scripts, etwa bei mehrseitigen Anwendungen wie Bestellvorgängen.
`$cgi->server_name()` | Skalar | Ermittelt den Namen des Server-Rechners, auf dem das CGI-Script läuft. Normalerweise ist dies der eingetragene Hostname des Rechners.
`$cgi->server_software()` | Skalar | Ermittelt den Namen und die Versionsnummer der Webserver-Software auf dem Server-Rechner.
`$cgi->url(-full => 1)` | Skalar | Ermittelt die vollständige Adresse des CGI-Scripts, aber ohne eventuell mit übergebene Parameter.
`$cgi->url(-path => 1)` | Skalar | Ermittelt zusätzliche, wie weitere Unterverzeichnisse notierte Angaben. Wenn das Script beispielsweise die Adresse `http://meine.seite.net/cgi-bin/test.pl` hat, aber mit `http://meine.seite.net/cgi-bin/test.pl/data/musicbase` aufgerufen wird, dann ermittelt dieser Befehl den Anteil `/data/musicbase`. Beachten Sie, dass Aufrufe dieser Art nicht von allen Webservern korrekt verarbeitet werden.
`$cgi->url(-query => 1)` | Skalar | Ermittelt die vollständige eigene Adresse des CGI-Scripts inklusive übergebener Parameter. Bei Aufrufen wie `http://meine.seite.net/cgi-bin/test.pl?user=Heino&wunsch=Volksmusik` wird also auch der Teil hinter dem Fragezeichen mit zurückgegeben.
`$cgi->url(-relative => 1)` | Skalar | Ermittelt den relativen HTTP-Pfad des CGI-Scripts aus Sicht des aktuellen Arbeitsverzeichnisses.
`$cgi->url_param()` | Liste | Ermittelt eine Liste aller Parameternamen, sofern Parameter übergeben wurden. Bei einem Script-Aufruf wie `http://meine.seite.net/cgi-bin/test.pl?user=Heino&wunsch=Volksmusik` wird also eine Liste mit den beiden Elementen `user` und `wunsch` ermittelt
`$cgi->url_param('wunsch')` | Skalar | Ermittelt den Wert eines dem Script übergebenen Parameter namens `wunsch`. Bei einem Script-Aufruf wie `http://meine.seite.net/cgi-bin/test.pl?user=Heino&wunsch=Volksmusik` wird also `Volksmusik` ermittelt.
`if($cgi->url_param())` | Liste, im booleschen Kontext ausgewertet | Ermittelt, ob dem Script über den URI irgendwelche Daten übergeben wurden. Im `if`-Zweig könnten Anweisungen stehen, die auf diesen Fall reagieren, während im `else`-Zweig davon ausgegangen werden kann, dass keine Parameter übergeben wurden.
`$cgi->user_agent()` | Skalar | Ermittelt die Bezeichnung, mit der sich der aufrufende Browser dem Server gegenüber ausgewiesen hat. Typische ermittelte Werte sind solche wie `Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)` (für den Internet Explorer 6.0).
`$cgi->user_name()` | Skalar | Ermittelt den Namen des aufrufenden Benutzers mit Hilfe verschiedener Abfragen. Moderne Browser verhindern allerdings ein Ausspionieren dieser Daten.
`$cgi->virtual_host()` | Skalar | Ermittelt den Domainnamen, mit dem der Browser das CGI-Script aufgerufen hat.

### Beachten Sie:

Diese Umgebungsdaten sind nicht dasselbe, was Sie eventuell als CGI-Umgebungsvariablen kennen. Sondern es sind Variablen, die zur Laufzeitumgebung Ihres Scripts gehören. In vielem allerdings ähneln sie den Umgebungsvariablen der CGI-Schnittstelle. Aber Sie können sich natürlich auch mit Hilfe des CGI-Moduls ein kleines Script zusammenstellen, das Ihnen eine Übersicht der CGI-Umgebungsvariablen liefert.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;

    print $cgi->header(),
          $cgi->start_html('Umgebungsvariablen'),
          $cgi->h1('Umgebungsvariablen'),
          $cgi->start_table(-border => '1')."\n",
            $cgi->Tr($cgi->th({-bgcolor => '#E0E0E0'},'Variablenname')."\n",
                     $cgi->th({-bgcolor => '#E0E0E0'},'Wert'))."\n";
    foreach(keys(%ENV)) {
      print $cgi->Tr($cgi->td($cgi->strong($_)),
                     $cgi->td($ENV{$_}))."\n";
    }
    print $cgi->Tr($cgi->th({-align => 'left', -bgcolor => '#E0E0E0', -colspan => '2'},
                             'insgesamt '.scalar keys(%ENV).' Umgebungsvariablen'))."\n",
          $cgi->end_table(),
          $cgi->end_html();

### Erläuterung:

Dieses zweite Beispielscript ist so ähnlich wie das erste aufgebaut. Auch hier wird eine Tabelle erzeugt. Aber es werden nicht bestimmte Umgebungsvariablen nach ihrem Wert gefragt, sondern es werden mit Hilfe einer `foreach`-Schleife alle ermittelbaren CGI-Umgebungsvariablen mitsamt der ihnen zugehörenden Werte in jeweils einer Tabellenzelle dargestellt.

## Cookies verwalten mit dem CGI-Modul

Cookies sind kleine Informationseinheiten in Form von Textdateien, die eine Webseite auf dem Rechner des aufrufenden Anwenders speichern kann. Das Speichern und Verwalten wird dabei vom Browser des Anwenders kontrolliert (Sie können festlegen, ob Ihr Browser Cookies annehmen darf oder nicht). Cookies erlauben es, anwender-individuelle Informationen wie den Zeitpunkt des letzten Besuchs, angeklickte Angebote oder auch login-Daten (das wird beispielsweise von diversen PHP-Boards gern genutzt) zu speichern und beim nächsten Aufruf wieder auszulesen. Das CGI-Modul unterstützt das Setzen und Lesen solcher Cookies.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;
    my $CTIME_String = localtime(time);
    my $altCookie = $cgi->cookie(-name=>'letzter_Besuch');
    my $neuCookie = $cgi->cookie(-name=>'letzter_Besuch',
                                -value=>$CTIME_String,
                                -expires=>'+3M',
                                -path=>'/');

    print $cgi->header(-cookie=>$neuCookie),
      $cgi->start_html("Cookie-Test"),
      $cgi->p("<b>Ihr letzter Besuchszeitpunkt dieser Seite war</b>: ", $altCookie || 'unbekannt'),
      $cgi->p("<b>Als neuer Besuchszeitpunkt wurde gespeichert</b>: ", $CTIME_String),
      $cgi->end_html();

### Erläuterung:

Das Beispielscript verwendet einen Cookie, mit dessen Hilfe es den letzten Aufrufzeitpunkt ermitteln kann und den aktuellen Aufrufzeitpunkt als neuen letzten speichert. Zur Kontrolle erzeugt es eine HTML-Ausgabe, in der dem Besucher der eingelesene alte Aufrufzeitpunkt und der neu gespeicherte Aufrufzeitpunkt mitgeteilt wird. Dazu bindet das Script zunächst mit `use CGI` das CGI-Modul ein und erzeugt mit `my $cgi = new CGI` eine neue Instanz des CGI-Objekts. Mit localtime(time) ermittelt es den aktuellen Zeitpunkt und speichert den Wert im Skalar `$CTIME_String`. Das Lesen und Setzen des Cookies steuert die Methode `cookie()` des CGI-Moduls. Über den Skalar `$cgi`, der an das erzeugte CGI-Objekt gebunden ist, greift das Script mit `$cgi->cookie()` auf die Methode zu.

Die Methode `cookie()` erwartet Argumente. Je nachdem, welche Argumente ihr übergeben werden, liest sie einen vorhandenen Cookie oder definiert einen neuen. Alle Argumente bestehen aus einem Argumentnamen und einem Wert. Der Argumentname beginnt mit einem Minuszeichen `-`. Hinter dem Argumentnamen folgt der Operator `=>` und dahinter die Angabe des gewünschten Wertes.

Zum Lesen genügt es, das Argument `-name` anzugeben. Ist ein Cookie mit diesem Namen vorhanden, dann liefert der Aufruf von `cookie()` dessen Wert zurück. Genau das geschieht im ersten Aufruf des obigen Beispiels. Der zurückgegebene Wert wird dort im Skalar `$altCookie` gespeichert. Im Beispiel hat das Cookie den Namen `letzer_Besuch`.

Zum Setzen eines Cookies müssen Sie mindestens zwei Argumente an `cookie()` übergeben, nämlich die Argumente `-name` und `-value`. Bei `-value` geben Sie an, welcher Wert gespeichert werden soll. Im obigen Beispiel ist das der Inhalt des zuvor errechneten Skalars `$CTIME_String`. Durch die Angabe von `-value` wird das Cookie aber noch nicht gesetzt. Dies geschieht erst beim Senden eines HTTP-Headers an den aufrufenden Browser. Dazu wird zunächst der Rückgabewert des Aufrufs von `cookie()` gespeichert, und zwar im Skalar `$neuCookie`. Dieser Skalar wird dann beim HTTP-Header, den Sie mit der Methode `header()` an den Browser senden, im Argument `-cookie` als Wert gesendet, so wie im obigen Beispiel gezeigt.

Ein weiteres wichtiges Argument der Methode `cookie()` ist `-expires`. Damit geben Sie an, wie lange der Browser das Cookie beim Anwender speichern soll. Wenn Sie `-expires` nicht angeben, behält der Browser das Cookie nur solange bis der Anwender den Browser beendet. Den gewünschten Speicherzeitraum geben Sie als Zahl mit voranstehendem Pluszeichen und einem nachgestellten Buchstaben für die Zeiteinheit an. Die Angabe `'+3M'` im Beispiel bedeutet "3 Monate". Andere Zeiteinheiten sind `s` (Sekunden), `m` (Minuten), `h` (Stunden), `d` (Tage) und `y` (Jahr). Darüber hinaus sind absolute Zeitangaben im UTC-Format erlaubt, wie z.B. `Friday, 08-Jun-2001 11:29:00 GMT+0100`.

Die Methode `cookie()` kennt daneben noch weitere Argumente. Mit `-path` geben Sie den HTTP-Pfad auf dem Server an, für den (einschließlich seiner Unterverzeichnisse) das Cookie gelten soll. Fehlt die Angabe, dann gilt das Cookie für die gesamte Domain ab der Dokumentwurzel. Mit `-domain` können Sie angeben, für welche Sub-Domain innerhalb der Hauptdomain das Cookie gelten soll (z.B. `-domain => news.aufdiesemserver.de`). Mit `-secure`, das als Wertzuweisung dann `true`, also beispielsweise `1` erwartet, erreichen Sie, dass das Cookie nur dann gesetzt wird, wenn die Serverumgebung eine SSL-geschützte Umgebung ist. Das ist wichtig, wenn Sie sensible Daten im Cookie übertragen, etwa die Kreditkartennummer des Anwenders, um ihm diese bei seinem nächsten Besuch gleich als Vorbelegung eines Formularfeldes anzubieten.

## Automatische Umleitungen (Redirects) mit dem CGI-Modul

Manche CGI-Scripts dienen dazu, den aufrufenden Anwender zu einer anderen Adresse weiterzuleiten und vorher eventuell noch ein paar Aufgaben zu erledigen.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $cgi = new CGI;

    open(FH,">>/usr/web/data/userlog.xml");
    print FH "<user-call>\n <remote-host>",
             $cgi->remote_host(),
             "</remote-host>\n <user-agent>",
             $cgi->user_agent(),
             "</user-agent>\n <goto-url>",
             $cgi->url_param('goto'),
             "</goto-url>\n <time-stamp>",
             localtime(time),
             "</time-stamp>\n</user-call>\n";
    close(FH);

    print $cgi->redirect($cgi->url_param('goto'));

### Erläuterung:

Das Beispiel-Script erwartet beim Aufruf im URI einen Parameter namens `goto`, dem wiederum eine gültige Adresse zugewiesen werden sollte. Angenommen, das Script hat die Adresse "http://localhost/cgi-bin/redirect.pl", dann wäre ein denkbarer Aufruf `http://localhost/cgi-bin/redirect.pl?goto=http%3A%2F%2Fde.selfhtml.org/`. Ein solcher Aufruf könnte beispielsweise als `href`-Attribut in einem Link stehen, der den Anwender eigentlich zu de.selfhtml.org führt, aber zuvor noch ein paar Daten über den Anwender sammelt.

Das Script bindet zunächst mit `use CGI` das CGI-Modul ein und erzeugt mit `my $cgi = new CGI` eine neue Instanz des CGI-Objekts. Die Weiterleitung ist dann wie in der untersten Anweisung des Beispiels gezeigt mit `print $cgi->redirect()` möglich. Als Argument wird der Methode `redirect()` die gewünschte Adresse übergeben, zu der die Umleitung erfolgen soll. Im Beispiel wird keine statische Adresse übergeben, sondern der Wert, der aus der Umgebungsvariablen `url_param('goto')` gewonnen wird. Darin ist der beim Script-Aufruf übergebene Wert von `goto` enthalten. Das Script tut also aus Anwendersicht nichts weiter, als die übergebene Adresse aufzurufen.

Zuvor schreibt das Script jedoch einige Daten über den Anwender in eine XML-Datei. In diese Datei werden Daten wie Hostname oder IP-Adresse des Anwenders, sein Browser-Typ, die Umleitungsadresse und der aktuelle Zeitstempel, ermittelt mit localtime(time), geschrieben. Zum Öffnen und Schließen der Datei verwendet das Script die üblichen Perl-Funktionen open und close. Die Daten werden wie üblich mit print und Angabe des Datei-Handles (im Beispiel `FH`) geschrieben.

## Sicherheitseinstellungen mit dem CGI-Modul

Das CGI-Modul bietet zwei wichtige Einstellmöglichkeiten an, mit denen Sie die Sicherheit eines CGI-Scripts vor böswilliger Benutzung erhöhen können. Die beiden Befehle sollten Sie zu Beginn des Scripts notieren, jedoch nach dem Einbinden des CGI-Moduls mit `use CGI`.

Befehl | Erläuterung
--- | ---
`$CGI::POST_MAX = 1024 * 100;` | Mit diesem Befehl legen Sie fest, wie viele Daten maximal an das CGI-Script übertragen werden können. Im Beispiel wird eine byte-gerechte Zahl errechnet, nämlich 100 Kilobyte. Wird der Wert überschritten, wird die Parameterliste gelöscht. Der entsprechende Fehlercode wird von der Methode `cgi_error` zurückgegeben.
`$CGI::DISABLE_UPLOADS = 1;` | Mit diesem Befehl können Sie verhindern, dass Dateien, die via Formular an das Script übertragen werden, also HTML-Tags der Sorte `<input type="file">`, automatisch in eine temporäre Datei gespeichert werden. Die entsprechenden Formulardaten werden dann beim Auswerten einfach übergangen. Interessant ist ein solcher Befehl beispielsweise, wenn das Script vorher nicht weiß, von wo es aufgerufen wird und welche Formulardaten es zu verarbeiten hat - etwa ein öffentlich zugänglicher Form-Mailer, der beliebige ausgefüllte HTML-Formulare an eine E-Mail-Adresse sendet.

| Computer und geschriebene Sprache
| CPAN-Module

© 2007 Impressum