## Modul CGI: Funktionen für die CGI-Programmierung

| Allgemeines zum CGI-Modul CGI-Modul in Scripts einbinden HTML-Ausgaben mit dem CGI-Modul Erweiterte Angaben für HTTP-Header und HTML-Dateikopf 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 zu den Standardmodulen. Es stellt eine Menge Funktionen bereit, die typische Routine-Aufgaben von CGI-Scripts übernehmen. Die enthaltenen Funktionen sind durch vielfachen Praxiseinsatz bewährt. Es ist deshalb sinnvoll, für CGI-Scripts auf die Ressourcen zurückzugreifen, die dieses Modul bereitstellt. Ein Nachteil des CGI-Moduls ist allerdings, dass es recht groß ist. Bei CGI-Scripts, die sehr häufig aufgerufen werden (z.B. Zugriffszähler-Scripts auf vielbesuchten Seiten), kann sich das bei der Belastung des Server-Rechners bemerkbar machen. In solchen Fällen ist es durchaus vertretbar, sich bewusst gegen die Verwendung des CGI-Moduls zu entscheiden. Bei den meisten CGI-Scripts ist die Verwendung des CGI-Moduls jedoch zu empfehlen. Denn das Modul übernimmt unter anderem auch eine ganze Reihe von automatischen Anpassungen an die Laufumgebung des Scripts, durch die mögliche Fehler vermieden werden.

Das CGI-Modul besteht aus einem Hauptmodul und verschiedenen Untermodulen. Die Untermodule leisten spezielle Aufgaben wie beispielsweise die Unterstützung des neueren Fast-CGI-Standards oder die Unterstützung so genannter Server-Pushs.

Es gibt zwei Verwendungsweisen des CGI-Moduls: eine objektorientierte und eine funktionsorientierte. Die objektorientiertere Verwendungsweise 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 in diesem Abschnitt auf die objektorientierte Verwendung.

## CGI-Modul in Scripts einbinden

Das folgende Beispiel zeigt, wie Sie das CGI-Modul in einem eigenen Perl-Script einbinden und im objektorientierten Stil verwenden.

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

    #!/usr/bin/perl -w

    use CGI;
    use CGI::Carp qw(fatalsToBrowser);
    $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 aber 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. Die Funktion bewirkt nämlich, dass alle Fehlermeldungen, die der Perl-Interpreter erzeugt, direkt im Browser ausgegeben werden.

Nachdem das CGI-Modul eingebunden ist, wird mit `$cgi = new CGI` eine neue Instanz des CGI-Objekts erzeugt. Mit dieser Anweisung stellen Sie die Weichen dafür, das CGI-Modul objektorientiert zu verwenden. Die Objektinstanz der CGI-Klasse ist nun über den Skalar `$cgi` ansprechbar. Über den Skalar haben Sie im weiteren Verlauf des Scripts Zugriff auf die Funktionen, die das CGI-Modul bereitstellt. Im objektorientierten Zusammenhang redet 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 jedoch meistens sehr oft brauchen, empfiehlt sich ein kurzer Name. Viele Programmierer arbeiten mit einbuchstabigen Namen wie z.B. `$q`.

Das obige Beispiel sendet ein einfaches "Hallo Welt" an den aufrufenden Browser. Wie immer, wenn ein CGI-Script etwas an den aufrufenden Browser sendet, muss es zuerst einen HTTP-Header erzeugen. Das CGI-Modul stellt dafür eine Funktion bzw. Methode namens `header()` zur Verfügung. Wenn dieser Methode kein Argument übergeben wird, erzeugt sie einen HTTP-Header für den Mime-Type `text/html`, also für die Ausgabe von HTML-Code. Im obigen Beispiel soll jedoch unformatierter Text gesendet werden. Deshalb wird der Funktion der Mime-Type `text/plain` übergeben.

An dem 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 ist.

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`.

## HTML-Ausgaben mit dem CGI-Modul

Das CGI-Modul stellt eigene Methoden bereit, um HTML-Code an den Browser zu senden.

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

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    my $cgi = new CGI;
    use CGI::Carp qw(fatalsToBrowser);

    my $Autor = "der Reiseonkel";
    $cgi->default_dtd('-//W3C//DTD HTML 4.01 Transitional//EN');

    print $cgi->header(),
          $cgi->start_html('Reisebericht vom Cap Ferret'),
          $cgi->h1('Reisebericht vom Cap Ferret'),
          $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 Cap Ferret selbst ist ein kleiner Landzipfel, der
            vor allem aus Ferienhäusern besteht. Austernzucht, Fischerei und
            Wassersport prägen die Atmosphäre Becken von Arcachon.'),
          $cgi->hr({-noshade => undef, -size => '1'}),
          $cgi->p({-style => 'color:red'}, "Autor: ", $cgi->i($Autor)),
          $cgi->end_html();

### Erläuterung:

Zunächst wird das CGI-Modul wie üblich mit `use CGI` eingebunden. Um es im objektorientierten Stil zu verwenden, wird mit `$cgi = new CGI` eine neue Instanz des CGI-Objekts erzeugt. Das Beispiel tut nichts anderes, als eine kleine, vollständige HTML-Datei an den Browser zu senden. Zunächst wird mit `$cgi->header()` der HTTP-Header für HTML erzeugt. Dann folgt der HTML-Code.

Der HTML-Code wird jedoch nicht wie üblich notiert, sondern durch Aufruf von Methoden, die das CGI-Modul bereitstellt. Für alle gängigen HTML-Elemente und HTML-Tags 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 Cap Ferret')` erzeugt beispielsweise ein komplettes HTML-Element mitsamt Inhalt. Der erzeugte Code lautet `<h1>Reisebericht vom Cap Ferret</h1>`. Auf die gleiche Weise funktioniert es mit den anderen HTML-Elementen. `$cgi->b('wichtiger Text')` würde beispielsweise den HTML-Code `<b>wichtiger Text</b>` erzeugen.
Mit der Methode `default_dtd` können Sie den DTD-Bezeichner festlegen, um das ausgegebene Dokument standardkonform gestalten zu können.

Die Überschrift im Beispiel könnte aber auch folgendermaßen notiert werden:
`$cgi->start_h1(),"Reisebericht vom Cap Ferret",$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 also 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_b()` und `$cgi->end_b()`.

Die Verwendung von 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, denn dazwischen steht ja die komplette HTML-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`. Das Argument, das ihr übergeben wird, schreibt sie als Inhalt des `title`-Elements.

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 bei 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 Angaben für HTTP-Header und HTML-Dateikopf

HTTP-Header können manchmal Zusatzinformationen erfordern. Und was den HTML-Dateikopf betrifft, so kann dieser ebenfalls wichtige allgemeine Angaben zur HTML-Datei enthalten, z.B. Meta-Tags oder die Attribute zur Seitengestaltung im einleitenden `<body>`-Tag.

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

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    my $cgi = new CGI;
    use CGI::Carp qw(fatalsToBrowser);
    $cgi->default_dtd('-//W3C//DTD HTML 4.01 Transitional//EN');

    print $cgi->header(-type    =>'text/html',
                       -expires =>'+1h'),
          $cgi->start_html(-title  =>'Testseite mit Link',
                           -author =>'selfhtml@teamone.de',
                           -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.teamone.de/'},'Link auf teamone.de')),
          $cgi->end_html();

### Erläuterung:

Das Script bindet mit `use CGI` das CGI-Modul ein und erzeugt mit `$cgi = new CGI` eine neue Instanz des CGI-Objekts. Bei der HTML-Ausgabe, die es anschließend erzeugt, 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 Standard-Argument: bei `header()` ist dies der Mime-Type, 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. Die beiden nachfolgenden Tabellen listen mögliche Argumente auf.

### Argumente beim HTTP-Header

Die folgende Tabelle listet auf, welche Angaben Sie zum HTTP-Header 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-Type 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.

### 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=>'selfhtml@teamone.de');` | Mit `-author` erzeugen Sie eine logische Beziehung zu einer Mailadresse. Das Beispiel erzeugt folgenden HTML-Code: `<LINK REV=MADE HREF="mailto:selfhtml%40teamone.de">`
`start_html(-base=>'http://myserver.com/');` | Mit `-base` bestimmen Sie die Basisadresse der ausgegebenen HTML-Seite. Das Beispiel erzeugt folgenden HTML-Code: `<BASE HREF="http://myserver.com/">`
`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

Viele CGI-Scripts werden über HTML-Formulare aufgerufen. Eine der wichtigsten Aufgaben des CGI-Moduls ist es deshalb, dem Script übergebene Formulardaten einzulesen und in bequemer Form zur Verfügung zu stellen. Das folgende Beispiel ist das gleiche wie das aus dem Abschnitt Beispiel für die Wechselwirkung zwischen HTML und CGI, diesmal jedoch unter Einsatz des CGI-Moduls.

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

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <title>Kommentarseite</title>
    </head>
    <body bgcolor="#E0E0E0" text="#000000">
    <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;
    my $cgi = new CGI;
    use CGI::Carp qw(fatalsToBrowser);

    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->b('Feldname: '),
                  $Feld,
                  $cgi->b(', Inhalt: '),
                  $cgi->param($Feld), "<br>";
          }
    print $cgi->end_html();

### Erläuterung:

Die HTML-Datei enthält ein Formular, das im einleitenden `<form>`-Tag beim `action`-Attribut das CGI-Script comments.pl aufruft. Als Methode für die Datenübertragung wird im Beispiel `post` gewählt. Die andere Methode, also `get`, wäre ebenso möglich. Das CGI-Modul erkennt die Übertragungsmethode automatisch.

Das CGI-Script comments.pl liest einfach die übergebenen Daten ein und sendet sie HTML-formatiert an den aufrufenden Browser zurück. Dazu bindet das Script zunächst mit `use CGI` das CGI-Modul ein und erzeugt mit `$cgi = new CGI` eine neue Instanz des CGI-Objekts. Anschließend ist über den Skalar `$cgi` der Zugriff auf Methoden des CGI-Objekts möglich. Entscheidend für die Formularverarbeitung ist die Methode `param()`, mit deren Hilfe sich das Script die übergebenen Daten abholen kann.

Bei der Methode `param` kommt es darauf an, in welchem Kontext sie aufgerufen wird. Dementsprechend unterschiedlich ist ihr Rückgabewert. Im obigen Beispiel steht die Anweisung `@Feldnamen = $cgi->param()`. Es handelt sich dabei 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. Es handelt sich um jene Namen, die im HTML-Formular bei der Definition der Formularfelder jeweils mit dem Attribut `name=` festgelegt wurden. Das Ermitteln aller Feldnamen in einer Liste ist insofern praktisch, als sich diese Namen später als Parameter an `param()` übergeben lassen. In der HTML-Ausgabe des Scripts ist ein solcher Aufruf von `param()` enthalten. Dort ist die Anweisung `$cgi->param($Feld)` notiert. Wenn `param()` ein Feldname als Parameter übergeben wird, liefert die Methode den zugehörigen Wert oder Inhalt des Feldes zurück. Der Kontext ist dann skalar. Im obigen Beispiel werden in der Schleife `foreach $Feld (@Feldnamen)` der Reihe nach alle Feldnamen des Formulars durchlaufen. Mit `$cgi->param($Feld)` kann dann auf den Inhalt des jeweils aktuellen Formularfeldes zugegriffen werden.

Die folgende Tabelle fasst die Aufrufmöglichkeiten von `param()` noch einmal 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.

## 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. Viele der Methoden liefern einfach nur Einzelheiten aus der vordefinierten Variablen `%ENV`.

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

    #!/usr/bin/perl -w

    use strict;
    use CGI;
    my $cgi = new CGI;
    use CGI::Carp qw(fatalsToBrowser);

    $cgi->default_dtd('-//W3C//DTD HTML 4.01 Transitional//EN');
    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 `$cgi = new CGI` eine neue Instanz des CGI-Objekts. Anschließend sendet es HTML-Code an den Browser, und zwar 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 `$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-Types 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 Web-Server ü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 Web-Servers 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 Serverrechners, 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 Serverrechner.
`$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 Scriptaufruf 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 Scriptaufruf 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 5.5; Windows 98)` (für den MS Internet Explorer 5.5).
`$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.

## Cookies verwalten mit dem CGI-Modul

Cookies sind kleine Informationseinheiten, die eine Webseite auf dem Rechner des aufrufenden Anwenders speichern kann. Das Speichern und Verwalten wird dabei vom Browser des Anwenders kontrolliert. Cookies erlauben es, anwender-individuelle Informationen wie den Zeitpunkt des letzten Besuchs oder angeklickte Angebote 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;
    my $cgi = new CGI;
    use CGI::Carp qw(fatalsToBrowser);

    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 `$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 die Methode `cookie()` kennt daneben noch weitere Argumente. Mit `-path` geben Sie den HTTP-Pfad auf dem Server an, für den und seine 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 Subdomain 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 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;
    my $cgi = new CGI;
    use CGI::Carp qw(fatalsToBrowser);

    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 Beispielscript 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%2Fwww.teamone.de/`. Ein solcher Aufruf könnte beispielsweise als `href`-Attribut in einem Link stehen, der den Anwender eigentlich zu www.teamone.de 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 `$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 Mailadresse sendet.

| Computer und geschriebene Sprache
| CPAN-Module

© 2001 selfhtml@teamone.de