Name

CGI - Common Gateway Interface


Übersicht

# Dieses CGI-Skript erzeugt ein Formular
# und gibt die eingegebenen Werte zurück.

use CGI qw/:standard/;
print header,
      start_html('Ein einfaches Beispiel'),
      h1('Ein einfaches Beispiel'),
      start_form,
      "Wie lautet Ihr Name? ",textfield('name'),p,
      "Wie lautet die Kombination?", p,
      checkbox_group(-name=>'words',
                     -values=>['eenie','meenie','minie','moe'],
                     -defaults=>['eenie','minie']), p,
      "Ihre Lieblingsfarbe? ",
      popup_menu(-name=>'color',
                 -values=>['rot','grün','blau','zartrosa']),p,
      submit,
      end_form,
      hr;

if (param()) {
      print "Ihr Name lautet",em(param('name')),p,
            "Die Schlüsselwörter sind: ",em(join(", ",param('words'))),p,
            "Ihre Lieblingsfarbe ist",em(param('color')),
            hr;
}


Abstract

Diese Perl-Bibliothek verwendet Perl5-Objekte, um die Generierung von Web-Formularen und das Parsing der entsprechenden Inhalte zu vereinfachen. Dieses Paket definiert CGI-Objekte, Entitäten, die Werte des aktuellen Query-Strings enthalten, sowie weitere Zustandsvariablen. Durch die Verwendung der Methoden eines CGI-Objekts können Sie die an Ihr Skript übergebenen Schlüsselwörter und Parameter untersuchen. Sie können auch Formulare erzeugen, deren Anfangswerte aus der aktuellen Query stammen (d.h., Zustandsinformationen bleiben erhalten). Das Modul stellt eine Reihe abkürzender Funktionen zur Verfügung, die reines HTML erzeugen und Eingabe- sowie Codierungsfehler reduzieren. Es stellt auch Funktionen für einige der fortgeschritteneren Features der CGI-Programmierung bereit, wie etwa das Upload von Dateien, Cookies, die Kaskadierung von Stylesheets, Server-Push und Frames.

CGI.pm erlaubt auch einen einfachen, funktionsorientierten Programmierstil, falls die objektorientierten Features nicht benötigt werden sollten.

Die aktuelle Version von CGI.pm finden Sie unter

http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
ftp://ftp-genome.wi.mit.edu/pub/software/WWW/


Beschreibung


Programmierstil

Für die Programmierung mit CGI.pm gibt es zwei verschiedene Ansätze: einen objektorientierten sowie einen funktionsorientierten Ansatz. Beim objektorientierten Ansatz erzeugen Sie ein oder mehrere CGI-Objekte und nutzen dann die Objektmethoden, um die verschiedenen Elemente der Seite zu generieren. Jedes CGI-Objekt beginnt mit einer Liste benannter Parameter, die Ihrem CGI-Skript vom Server übergeben wurden. Sie können diese Objekte verändern, in einer Datei oder einer Datenbank abspeichern und regenerieren. Weil jedes Objekt dem "Zustand" des CGI-Skripts entspricht, und weil die Parameterliste jedes Objekts unabhängig von den anderen existiert, ist es Ihnen möglich, den Zustand des Skripts zu sichern und später wiederherzustellen.

Mit dem objektorientierten Ansatz können Sie eine einfache "Hallo Welt"-HTML-Seite wie folgt erzeugen:

#!/usr/local/bin/perl
use CGI;                             # CGI-Routinen laden.
$q = new CGI;                        # Neues CGI-Objekt erzeugen.
print $q->header,                    # HTTP-Header generieren.
      $q->start_html('Hallo Welt'),  # HTML einleiten.
      $q->h1('Hallo Welt'),          # Level-1-Header
      $q->end_html;                  # HTML abschließen.

Beim funktionsorientierten Ansatz gibt es ein Standard-CGI-Objekt, mit dem Sie aber nur selten direkt arbeiten. Statt dessen rufen Sie einfach Funktionen auf, um CGI-Parameter zu ermitteln, HTML-Tags zu erzeugen, Cookies zu verwalten und so weiter. Mit diesem Ansatz steht Ihnen eine klarere Programmierschnittstelle zur Verfügung, allerdings sind Sie dabei auf nur jeweils ein Objekt beschränkt. Das nachfolgende Beispiel gibt die gleiche Seite aus wie oben, verwendet dabei aber die funktionsorientierte Schnittstelle. Die Hauptunterschiede liegen darin, daß wir nun eine Reihe von Funktionen in unseren Namensraum importieren (üblicherweise die "standard"-Funktionen) und kein CGI-Objekt erzeugen müssen.

#!/usr/local/bin/perl
use CGI qw/:standard/;           # Standard-CGI-Routinen laden.
print header,                    # HTTP-Header generieren.
      start_html('Hallo Welt'),  # HTML einleiten.
      h1('Hallo Welt'),          # Level-1-Header
      end_html;                  # HTML abschließen.

Die Beispiele in diesem Dokument verwenden den objektorientierten Ansatz. Wichtige Informationen zur funktionsorientierten Programmierung mit CGI.pm finden Sie unter "HOW TO IMPORT FUNCTIONS".


Aufruf der CGI.PM-Routinen

Die meisten Routinen von CGI.pm akzeptieren mehrere, manchmal bis zu 20 optionale Argumente! Um diese Schnittstelle zu vereinfachen, verwenden alle Routinen beim Aufruf ein benanntes Argument, das wie folgt aussieht:

print $q->header(-type=>'image/gif',-expires=>'+3d');

Jedem Argumentnamen steht ein Bindestrich voran. Weder die Schreibweise noch die Reihenfolge spielen in der Argumentliste eine Rolle. -type, -Type und -TYPE sind alle erlaubt. Tatsächlich muß nur das erste Argument mit einem Bindestrich beginnen. Besitzt das erste Argument einen Bindestrich, übernimmt CGI.pm den Bindestrich für alle nachfolgenden Argumente automatisch.

Wenn Sie möchten, können Sie auf den Bindestrich sogar ganz verzichten. Nachdem Sie ein CGI-Objekt erzeugt haben, rufen Sie die Methode use_named_parameters() mit einem Wert ungleich null auf. Damit teilen Sie CGI.pm mit, daß Sie ausschließlich benannte Parameter verwenden wollen:

$query = new CGI;
$query->use_named_parameters(1);
$field = $query->radio_group('name'=>'OS',

                             'values'=>['Unix','Windows','Macintosh'],
                             'default'=>'Unix');

Verschiedene Routinen werden häufig mit nur einem Argument aufgerufen. Bei diesen Routinen können Sie das einzelne Argument ohne den Argumentnamen angeben. header() ist eine dieser Routinen, wobei hier das einzelne Argument den Typ des Dokuments bestimmt.

print $q->header('text/html');

Weitere gleichgelagerte Routinen werden nachfolgend noch dokumentiert.

Manchmal erwarten benannte Argumente einen Skalar, manchmal eine Referenz auf ein Array und manchmal eine Referenz auf einen Hash. Häufig können Sie einen beliebigen Argumenttyp übergeben, und die Routine sucht sich das passendste Argument aus. Zum Beispiel wird die Routine param() dazu benutzt, um einzelne oder mehrere Werte festzulegen. Diese beiden Fälle sind nachfolgend aufgeführt:

$q->param(-name=>'veggie',-value=>'tomato');
$q->param(-name=>'veggie',-value=>'[tomato','tomahto','potato','potahto']);

Viele Routinen in CGI.pm sind im Modul nicht explizit definiert, sondern werden nach Bedarf generiert. Dabei handelt es sich um die "HTML-Kurzformen", die HTML-Tags erzeugen, die dann in dynamisch generierten Seiten verwendet werden. HTML-Tags besitzen sowohl Attribute (die attribut="wert"-Paare innerhalb des Tags selbst) als auch einen Inhalt (der Teil zwischen den öffnenden und schließenden Paaren). Um zwischen Attribut und Inhalt zu unterscheiden, verwendet CGI.pm eine Konvention, bei der HTML-Argumente als erstes Argument in Form einer Hashreferenz übergeben werden, während die Inhalte, falls es welche gibt, in den nachfolgenden Argumenten übergeben werden. Das sieht dann so aus:

Code                           HTML
----                           --------------
h1()                           <H1>
h1('irgendein','Inhalt');      <H1>irgendein Inhalt</H1>
h1({-align=>left});            <H1 ALIGN="LEFT">
h1({-align=>left},'Inhalt');   <H1 ALIGN="LEFT">Inhalt</H1>

HTML-Tags werden später noch ausführlich beschrieben.

Viele CGI.pm-Neulinge sind verwirrt durch die Aufrufkonventionen für HTML-Kurzformen (bei denen die HTML-Tag-Attribute von geschweiften Klammern umschlossen sein müssen) und für normale Routinen (bei denen die Attribute auch ohne geschweifte Klammern verarbeitet werden). Lassen Sie sich nicht irritieren. Der Bequemlichkeit halber sind geschweifte Klammern überall optional, die Ausnahme bilden nur die HTML-Kurzformen. Wenn Sie wollen, können Sie jede Routine, die benannte Argumente verwendet, mit geschweiften Klammern aufrufen:

print $q->header( {-type=>'image/gif',-expires=>'+3d'} );

Wenn Sie den Switch -w verwenden, erhalten Sie eine Warnung, daß einige Argumentnamen von CGI.pm mit in Perl integrierten Funktionen kollidieren. Am häufigsten betroffen ist hiervon das Argument -values, mit dem aus mehreren Werten bestehende Menüs, Gruppen von Radiobuttons und ähnliches erzeugt werden. Um diese Warnung zu vermeiden, haben Sie mehrere Möglichkeiten:

  1. Verwenden Sie, falls vorhanden, einen anderen Namen für das Argument. Zum Beispiel ist -value ein Alias für -values.
  2. Verwenden Sie Großschreibung, z.B. -Values
  3. Stellen Sie Quoting-Zeichen um den Argumentnamen, z.B. '-values'

Viele Routinen stellen etwas mehr oder weniger Sinnvolles mit einem unbekannten benannten Argument an. Zum Beispiel können Sie vom Standard abweichende HTTP-Header-Felder erzeugen, indem Sie diese als benannte Argumente übergeben:

print $q->header(-type  =>  'text/html',
                 -cost  =>  'Three smackers',
                 -annoyance_level => 'high',
                 -complaints_to   => 'bit bucket');

Damit wird der folgende, vom Standard abweichende HTTP-Header erzeugt:

HTTP/1.0 200 OK
Cost: Three smackers
Annoyance-level: high
Complaints-to: bit bucket
Content-type: text/html

Beachten Sie die Art, wie Unterstriche automatisch in Bindestriche umgewandelt werden. HTML-generierende Routinen führen eine andere Form der Umwandlung durch.

Dieses Feature ermöglicht es Ihnen, mit den sich schnell ändernden HTTP- und HTML-"Standards" Schritt zu halten.


Erzeugung eines neuen Query-Objekts (Objektorientierter Stil)

$query = new CGI;

Analysiert ("parst") die Eingabe (über POST sowie über GET) und speichert sie in einem Perl5-Objekt namens $query.


Erzeugung eines neuen Query-Objekts aus einer Eingabedatei

$query = new CGI(INPUTFILE);

Übergeben Sie ein Dateihandle an die new()-Methode, werden die Parameter aus der Datei (oder STDIN, oder was auch immer) gelesen. Diese Datei kann jede der beim Thema Debugging beschriebenen Formen besitzen (beispielsweise würde eine Reihe von TAG=WERT-Paaren - durch Zeilenvorschübe getrennt - funktionieren). Üblicherweise wird diese Art von Datei mit der save()-Methode (siehe unten) erzeugt. Mehrere Datensätze können gesichert und wiederhergestellt werden.

Perl-Puristen werden gerne hören, daß diese Syntax Referenzen auf Dateihandles - ja sogar Referenzen auf Dateihandle-Globs - erlaubt, die den "offiziellen" Weg für die Übergabe eines Dateihandles darstellen:

$query = new CGI(\*STDIN);

Sie können das CGI-Objekt auch mit einem FileHandle- oder IO::File-Objekt initialisieren.

Wenn Sie mit der funktionsorientierten Schnittstelle arbeiten und den CGI-Zustand über ein Dateihandle initialisieren wollen, müssen Sie das mit restore_parameters() erledigen. Damit wird das Standard-CGI-Objekt über das angegebene Dateihandle (re)initialisiert.

open (IN,"test.in") || die;
restore_parameters(IN);
close IN;

Sie können das Query-Objekt auch über eine Hashreferenz initialisieren:

$query = new CGI( {'dinosaur'=>'barney',
                   'song'=>'I love you',
                   'friends'=>[qw/Jessica George Nancy/]}
                );

oder über einen richtig formatierten, URL-geschützten c:

$query = new CGI('dinosaur=barney&color=purple');

oder über ein bereits existierendes CGI-Objekt (momentan wird damit die Parameterliste kopiert, nicht aber die objektspezifischen Felder wie etwa Autoescaping):

$old_query = new CGI;
$new_query = new CGI($old_query);

Um eine leere Query zu erzeugen, initialisieren Sie sie über einen leeren String oder Hash:

$empty_query = new CGI("");

- oder -

$empty_query = new CGI({});


Erzeugung einer Liste mit den Schlüsselwörtern der Query

@keywords = $query->keywords

Wenn das Skript als Ergebnis einer <ISINDEX>-Suche ausgeführt wird, können die erkannten Schlüsselwörter mit der Methode keywords() ermittelt werden. Zurückgeliefert wird eine entsprechende Liste.


Bestimmung der Namen aller an Ihr Skript übergebenen Parameter

@names = $query->param

Wurde das Skript mit einer Parameterliste aufgerufen (z.B. "name1=wert1&name2=wert2&name3=wert3"), gibt die Methode param() eine Liste aller Parameternamen zurück. Wurde das Skript als <ISINDEX>-Skript aufgerufen, erhalten Sie nur einen einzelnen Parameter namens 'keywords'.

HINWEIS: Seit der Version 1.5 enthält das Array die Parameternamen in der gleichen Reihenfolge, wie sie vom Browser übergeben wurden. Üblicherweise entspricht das der gleichen Reihenfolge, in der die Parameter im Formular definiert sind (was aber nicht Teil der Specs ist und daher nicht garantiert wird).


Bestimmung der oder des Werte(s) eines einzelnen benannten Parameters

@values = $query->param('foo');

- oder -

$value = $query->param('foo');

Übergeben Sie der param()-Methode ein einzelnes Argument, um den Wert des benannten Parameters zu bestimmen. Besitzt der Parameter mehrere Werte (z.B. mehrere aktive Einträge einer Scroll-Liste), können Sie auch ein Array anfordern. Anderenfalls gibt die Methode einen einzelnen Wert zurück.


Setzen der oder des Werte(s) eines benannten Parameters

$query->param('foo','ein','array','mit','werten');

Damit setzen Sie den Wert des benannten Parameters 'foo' auf ein Wertearray. Dies ist eine Möglichkeit, den Wert eines Feldes zu ändern, NACHDEM das Skript bereits einmal aufgerufen wurde. (Eine andere Möglichkeit besteht darin, den Parameter -override zu verwenden, der von allen Methoden akzeptiert wird, die Formularelemente generieren.)

param() erkennt auch einen an benannten Parametern orientierten Aufrufstil, der später noch im Detail erläutert wird:

$query->param(-name=>'foo',-values=>['ein','array','mit','werten']);

- oder -

$query->param(-name=>'foo',-value=>'der wert');


Anhängen zusätzlicher Werte an einen benannten Parameter

$query->append(-name=>'foo',-values=>['noch','mehr','werte']);

Damit wird ein Wert oder eine Werteliste an den benannten Parameter angehängt. Die Werte werden an das Ende des Parameters angehängt, wenn dieser bereits existiert. Anderenfalls wird der Parameter erzeugt. Beachten Sie, daß diese Methode nur die Aufrufsyntax für benannte Argumente erkennt.


Importieren aller Parameter in einen Namensraum

$query->import_names('R');

Dies erzeugt eine Reihe von Variablen im Namensraum 'R', also beispielsweise $R::foo, @R:foo. Für Schlüsselwortlisten erscheint eine Variable @R::keywords. Wird kein Namensraum angegeben, geht die Methode von 'Q' aus. WARNUNG: Importieren Sie nichts nach 'main' - das ist ein ernsthaftes Sicherheitsrisiko!!!!

Bei älteren Versionen hieß diese Methode import(). Seit der Version 2.20 wurde dieser Name vollständig entfernt, um einen Konflikt mit dem Perl-Moduloperator import zu vermeiden.


Einen Parameter vollständig löschen

$query->delete('foo');

Diese Routine löscht einen Parameter vollständig. Ist manchmal nützlich für das Zurücksetzen einzelner Parameter, die Sie zwischen Skriptaufrufen nicht weitergeben wollen.

Falls Sie die funktionsorientierte Schnittstelle verwenden, benutzen Sie statt dessen "Delete()", um einen Konflikt mit dem in Perl integrierten delete-Operator zu verhindern.


Löschen aller Parameter

$query->delete_all();

Damit wird das CGI-Objekt vollständig gelöscht. Nützlich, um sicherzustellen, daß beim Erzeugen eines Formulars alle Standardwerte verwendet werden.

Verwenden Sie bei der funktionsorientierten Schnittstelle die Funktion Delete_all().


Direkter Zugriff auf die Parameterliste

$q->param_fetch('address')->[1] = '1313 Mockingbird Lane';
unshift @{$q->param_fetch(-name=>'address')},'George Munster';

Wenn Sie auf die Parameterliste in einer Weise zugreifen müssen, die durch die obigen Methoden nicht abgedeckt wird, können Sie eine direkte Referenz ermitteln, indem Sie die Methode param_fetch() mit dem Namen des Parameters aufrufen. Auf diese Weise erhalten Sie eine Arrayreferenz auf die benannten Parameter zurück, die Sie auf jede gewünschte Weise manipulieren können.

Sie können auch mit benannten Argumenten arbeiten, indem Sie das Argument -name verwenden.


Den Zustand des Skripts in einer Datei sichern

$query->save(FILEHANDLE)

Schreibt den aktuellen Zustand des Formulars an das übergebene Dateihandle. Diesen Zustand können Sie wiederherstellen, indem Sie ein Filehandle an die new()-Methode übergeben. Beachten Sie, daß es sich bei diesem Dateihandle um eine Datei, eine Pipe oder was auch immer handeln kann!

Das Format der gesicherten Datei ist wie folgt:

NAME1=WERT1
NAME1=WERT1'
NAME2=WERT2
NAME3=WERT3
=

Sowohl der Name als auch der Wert sind URL-geschützt. CGI-Parameter mit mehreren Werten werden mit sich wiederholenden Namen angegeben. Datensätze einer Session werden durch ein einzelnes Gleichheitszeichen getrennt. Sie können mehrere Datensätze sichern und mit wiederholten Aufrufen von new wieder einlesen. Sie können das auch über mehrere Sessions hinweg machen, indem Sie die Datei im Anhänge-Modus öffnen. Auf diese Weise können Sie ein einfaches Gästebuch aufbauen oder eine Liste der Benutzerabfragen führen. Hier ein kurzes Beispiel für die Erzeugung von Datensätzen über mehrere Sessions hinweg:

use CGI;

open (OUT,">>test.out") || die;
$records = 5;
foreach (0..$records) {
    my $q = new CGI;
    $q->param(-name=>'counter',-value=>$_);
    $q->save(OUT);
}
close OUT;

# Erneut öffnen (lesen)
open (IN,"test.out") || die;
while (!eof(IN)) {
    my $q = new CGI(IN);
    print $q->param('counter'),"\n";
}

Das zum Sichern/Wiederherstellen verwendete Format entspricht dem vom Whitehead Genome Center verwendeten Format zum Datenaustausch ("Boulderio") und kann mit Boulderio-Utilities verändert, ja sogar in Datenbanken übernommen werden. Details hierzu finden Sie unter http://www.genome.wi.mit.edu/genome_software/other/boulder.html.

Sie können diese Methode auch mit der funktionsorientierten Schnittstelle verwenden. Der exportierte Name dieser Methode lautet save_parameters().


Verwendung der funktionsorientierten Schnittstelle

Um die funktionsorientierte Schnittstelle verwenden zu können, müssen Sie angeben, welche CGI.pm-Routinen bzw. welcher Satz von Routinen in den Namensraum Ihres Skripts zu importieren ist. Mit diesem Import ist ein kleiner Overhead verbunden, aber er ist nicht sehr groß.

use CGI <Liste der Methoden>;

Die aufgeführten Methoden werden in das aktuelle Paket importiert. Sie können sie direkt aufrufen, ohne vorher ein CGI-Objekt erzeugen zu müssen. Das folgende Beispiel zeigt, wie die Methoden param() und header() importiert und dann direkt genutzt werden können:

use CGI 'param','header';
print header('text/plain');
$zipcode = param('zipcode');

Weitaus häufiger werden Sie einen oft verwendeten Satz von Funktionen importieren, indem Sie diese Gruppe über den Namen ansprechen. Allen Funktionsgruppen wird ein Doppelpunkt vorangestellt, also beispielsweise ":html3" (für im HTML3-Standard definierte Tags).

Hier ist eine Liste der importierbaren Funktionsgruppen:

:cgi
Import aller Methoden zum CGI-Handling, wie etwa param(), path_info() und so weiter.
:form
Import aller Methoden zur Formulargenerierung, etwa textfield().
:html2
Import aller Methoden, mit denen HTML-2.0-Standardelemente generiert werden können.
:html3
Import aller Methoden, mit denen bei HTML 3.0 vorgeschlagene Elemente (wie etwa <table>, <super> und <sub>) generiert werden können.
:netscape
Import aller Methoden, die Netscape-spezifische HTML-Erweiterungen generieren.
:html
Import aller HTML-generierenden Kurzformen (z.B. 'html2' + 'html3' + 'netscape').
:standard
Import der "Standard"-Features 'html2', 'html3', 'form' und 'cgi'.
:all
Import aller verfügbaren Methoden. Für eine vollständige Liste müssen Sie sich den CGI.pm-Code an der Stelle ansehen, an der die Variable %TAGS definiert ist.

Importieren Sie einen Funktionsnamen, der kein Bestandteil von CGI.pm ist, betrachtet das Modul ihn als neuen HTML-Tag und generiert die entsprechende Unterroutine. Diese können Sie dann wie jeden anderen HTML-Tag verwenden. Auf diese Weise sind Sie dem sich schnell ändernden HTML-"Standard" gewachsen. Nehmen wir beispielsweise einmal an, Microsoft kommt mit einem neuen Tag namens <GRADIENT> heraus (der den Bildschirmhintergrund des Benutzers mit einem ständig rotierenden Farbspektrum füllt, bis seine Maschine neu gebootet wird). Sie müssen nicht auf eine neue Version von CGI.pm warten, um den neuen Tag direkt nutzen zu können:

use CGI qw/:standard :html3 gradient/;
print gradient({-start=>'red',-end=>'blue'});

Beachten Sie, daß CGI.pm im Interesse der Ausführungsgeschwindigkeit nicht die Standard-Exporter-Syntax zur Angabe von Ladesymbolen verwendet. Dies könnte sich in Zukunft ändern.

Wenn Sie irgendeine der zustandsverarbeitenden CGI-Methoden oder formulargenerierende Methoden verwenden, wird beim ersten Aufruf einer Methode, die ein Objekt benötigt, automatisch ein Standard-CGI-Objekt erzeugt und initialisiert. Hierzu gehören param(), textfield(), submit() und so weiter. (Falls Sie direkt auf das CGI-Objekt zugreifen müssen, finden Sie es in der globalen Variable $CGI::Q.) Durch den Import von CGI.pm-Methoden können Sie rein optisch sehr elegante Skripten erzeugen:

use CGI qw/:standard/;
print 
    header,
    start_html('Einfaches Skript'),
    h1('Einfaches Skript'),
    start_form,
    "Wie lautet Ihr Name? ",textfield('name'),p,
    "Wie lautet die Kombination?",
    checkbox_group(-name=>'words',
                   -values=>['eenie','meenie','minie','moe'],
                   -defaults=>['eenie','moe']),p,
    "Ihre Lieblingsfarbe?",
    popup_menu(-name=>'color',
               -values=>['rot','grün','blau','zartrosa']),p,
    submit,
    end_form,
    hr,"\n";

if (param) {
    print 
        "Ihr Name ist ",em(param('name')),p,
        "Die Schlüsselwörter sind: ",em(join(", ",param('words'))),p,
        "Ihre Lieblingsfarbe ist",em(param('color')),".\n";
}
print end_html;


Pragmas

Zusätzlich zu den Funktionsgruppen gibt es eine Reihe von Pragmas, die importiert werden können. Pragmas, denen immer ein Bindestrich vorsteht, ändern auf verschiedene Arten die Funktionsweise der CGI.pm-Funktionen. Pragmas, Funktionsgruppen und einzelne Funktionen können alle in der gleichen use()-Zeile importiert werden. Zum Beispiel importiert die folgende use-Anweisung die Gruppe der Standardfunktionen und deaktiviert den Debugging-Modus (Pragma -no_debug):

use CGI qw/:standard -no_debug/;

Nachfolgend die aktuelle Liste der Pragmas:

-any
Wenn Sie use CGI -any angeben, wird jede vom Query-Objekt nicht erkannte Methode als neuer HTML-Tag interpretiert. Auf diese Weise können Sie auch die nächste ad hoc-HTML-Erweiterung von Netscape oder Microsoft verarbeiten. Neue oder nicht unterstützte Tags lassen sich so ganz einfach einbinden:
use CGI qw(-any);
$q=new CGI;
print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});
Weil die Verwendung von <cite>any</cite> dazu führt, daß jeder falsch geschriebene Methodenname als HTML-Tag interpretiert wird, sollten Sie es nur sehr vorsichtig oder gar nicht einsetzen.
-compile
Sorgt dafür, daß die angegebenen automatisch geladenen Methoden vorab kompiliert werden, statt dies auf später zu verschieben. Nützlich bei Skripten, die für eine längere Zeit unter FastCGI oder mod_perl laufen sollen, oder für solche Skripten, die für Malcom Beatties Perl-Compiler gedacht sind. Verwenden Sie das Pragma zusammen mit den Methoden bzw. den Methoden-Familien, deren Verwendung Sie planen.
use CGI qw(-compile :standard :html3);
oder sogar
use CGI qw(-compile :all);
Beachten Sie, daß diese Verwendung des -compile-Pragmas den Effekt hat, daß alle Funktionen in den aktuellen Namensraum kompiliert werden. Wollen Sie kompilieren, ohne zu importieren, verwenden Sie statt dessen die Methode compile() (siehe unten).
-nph
Läßt CGI.pm einen Header erzeugen, der für ein NPH-Skript ("no parsed header") geeignet ist. Möglicherweise müssen Sie noch andere Dinge tun, um dem Server mitzuteilen, daß es sich um ein NPH-Skript handelt. Beachten Sie hierzu die noch folgende Diskussion von NPH-Skripten.
-newstyle_urls
name=value-Paare in Query-Strings werden durch ein Semikolon anstelle eines Ampersand (Kaufmannsund) getrennt. Zum Beispiel:
?name=fred;age=24;favorite_color=3
Semikolonseparierte Query-Strings sind immer akzeptiert, werden aber von self_url() und query_string() nicht emittiert, solange das Pragma -newstyle_urls nicht angegeben ist.
-autoload
Überschreibt den Autoloader so, daß alle nicht erkannten Funktionen in Ihrem Programm an CGI.pm zur möglichen Evaluierung weitergegeben werden. Auf diese Weise können Sie alle CGI.pm-Funktionen nutzen, ohne sie in Ihre Symboltabelle aufnehmen zu müssen, was für mod_perl-Benutzer von besonderem Interesse ist, die sich Gedanken um den Speicherbedarf machen. Warnung: Ist -autoload aktiv, können Sie den sogenannten "Gedichts-Modus" ("poetry mode", d.h. Funktionen ohne runde Klammern) nicht verwenden. Benutzen Sie also hr() statt hr, oder stellen Sie so etwas wie use subs qw/hr p header/ an den Anfang Ihres Skripts.
-no_debug
Deaktiviert die Features der Kommandozeilenverarbeitung. Soll ein CGI.pm-Skript von der Kommandozeile aufgerufen werden, um HTML zu erzeugen, und wollen Sie verhindern, daß CGI-Parameter von der Standardeingabe oder der Kommandozeile angefordert werden, dann verwenden Sie dieses Pragma.
use CGI qw(-no_debug :standard);
Möchten Sie die Kommandozeilenparameter, nicht aber die Standardeingabe verarbeiten, sollte folgendes helfen:
use CGI qw(-no_debug :standard);
restore_parameters(join('&',@ARGV));
Details finden Sie im Abschnitt zum Debugging.
-private_tempfiles
CGI.pm kann auch per Upload übergebene Dateien verarbeiten. Üblicherweise wird die hochgeladene Datei in einem temporären Verzeichnis abgelegt und gelöscht, sobald die Datei verarbeitet wurde. Allerdings eröffnet das die Möglichkeit eines Lauschangriffs, wie er im Abschnitt zum Datei-Upload beschrieben wird. Ein anderer CGI-Skript-Autor könnte sich diese Daten während des Uploads ansehen, selbst wenn es sich um vertrauliche Informationen handelt. Bei Unix-Systemen sorgt das Pragma -private_tempfiles dafür, daß die temporäre Datei direkt nach dem Öffnen, aber vor dem Schreiben irgendwelcher Daten, abgekoppelt wird, was das Risiko eines Lauschangriffs eliminiert.

Generierung dynamischer Dokumente

Die meisten Funktionen von CGI.pm dienen der dynamischen Generierung von Dokumenten. Im allgemeinen erzeugen Sie zuerst den HTTP-Header, dem dann das eigentliche Dokument folgt. CGI.pm stellt Funktionen zur Generierung von HTTP-Headern unterschiedlicher Typen sowie zur Generierung von HTML zur Verfügung. Für GIF-Grafiken können Sie das Modul GD.pm verwenden.

Jede dieser Funktionen erzeugt ein HTML- oder HTTP-Fragment, das direkt im Browser erscheint, an einen String angehängt oder zur späteren Verwendung in einer Datei abgelegt werden kann.

Erzeugung eines Standard-HTTP-Headers

Normalerweise geben Sie in Ihrem CGI-Skript als erstes einen HTTP-Header aus. Damit teilen Sie dem Browser mit, welche Art von Dokument er zu erwarten hat, und übergeben noch optionale Informationen wie etwa die Sprache, das Ablaufdatum und ob das Dokument im Cache abgelegt werden kann. Der Header kann auch an spezielle Bedürfnisse angepaßt werden, beispielsweise an einen Server-Push oder kostenpflichtige Seitenabrufe.

print $query->header;

- oder -

print $query->header('image/gif');

- oder -

print $query->header('text/html','204 No response');

- oder -

print $query->header(-type=>'image/gif',
                     -nph=>1,
                     -status=>'402 Payment required',
                     -expires=>'+3d',
                     -cookie=>$cookie,
                     -Cost=>'$2.00');

header() gibt den Content-type:-Header zurück. Sie können einen eigenen MIME-Typ angeben, anderenfalls wird text/html genommen. Als optionalen zweiten Parameter können Sie den Statuscode zusammen mit einer für Menschen verständlichen Nachricht übergeben. Zum Beispiel können Sie 204, "No response" angeben, um ein Skript zu erzeugen, das den Browser anweist, nichts zu tun.

Das letzte Beispiel zeigt die Verwendung benannter Argumente zur Übergabe von Argumenten an CGI-Methoden, die mit benannten Parametern arbeiten. Bekannte Parameter sind -type, -status, -expires und -cookie. Bei allen anderen Parametern wird der führende Bindestrich entfernt, und die Parameter werden in Header-Felder umgewandelt, was es Ihnen erlaubt, jeden von Ihnen gewünschten HTTP-Header anzugeben. Enthaltene Unterstriche werden dabei in Bindestriche umgewandelt:

print $query->header(-Content_length=>3002);

Die meisten Browser legen die Ausgaben von CGI-Skripten nicht im Cache ab. Jedesmal lädt der Browser die Seite erneut, und das Skript wird erneut aufgerufen. Sie können dieses Verhalten mit dem Parameter -expires ändern. Geben Sie diesem Parameter ein absolutes oder relatives Ablaufintervall mit, legen einige Browser und Proxy-Server die Ausgabe des Skripts im Cache ab, bis die angegebene Ablaufzeit vorbei ist. Die folgenden Formen sind für das -expires-Feld gültig:

+30s                              30 Sekunden von nun an
+10m                              10 Minuten von nun an
+1h                               eine Stunde von nun an
-1d                               gestern (d.h. so schnell wie möglich)
now                               jetzt
+3M                               in drei Monaten
+10y                              in 10 Jahren
Thursday, 25-Apr-1999 00:40:33 GMT  zum angegebenen Zeitpunkt (Zeit & Datum)

Der Parameter -cookie generiert einen Header, der den Browser anweist, bei allen nachfolgenden Transaktionen mit dem Skript ein sogenanntes "Magic Cookie" bereitzustellen. Netscape-Cookies besitzen ein spezielles Format, das interessante Attribute wie etwa das Ablaufdatum umfaßt. Verwenden Sie die Methode cookie() zur Erzeugung und Bestimmung von Session-Cookies.

Wird der Parameter -nph auf wahr gesetzt, werden die für ein NPH-Skript ("no-parse-header") benötigten Header generiert. Das ist in Verbindung mit bestimmten Servern besonders wichtig, etwa dem Microsoft Internet Explorer, weil diese erwarten, daß alle Skripten NPH-Skripten sind.

Generierung eines Redirection-Headers

print $query->redirect('http://somewhere.else/in/movie/land');
Manchmal wollen Sie kein eigenes Dokument erzeugen, sondern den Browser einfach irgendwo anders hin "umleiten" (redirect), wobei möglicherweise eine URL gewählt wird, die von der Tageszeit oder der Identität des Benutzers abhängt.

Die redirect()-Funktion leitet den Browser an eine andere URL um. Wenn Sie Redirection auf diese Weise verwenden, dürfen Sie zusätzlich nicht noch einen Header mit ausgeben. Seit der Version 2.0 wird sowohl der inoffizielle Location:-Header als auch der offizielle URI:-Header erzeugt. Das sollte den meisten Servern und Browsern genügen.

Ein Hinweis, den ich hier noch anbringen möchte, ist, daß relative Links möglicherweise nicht richtig funktionieren, wenn Redirection auf ein anderes Dokument Ihrer Site verweist. Das liegt an einer gutgemeinten Optimierung, die von einigen Servern durchgeführt wird. Die Lösung liegt darin, die vollständige URL (einschließlich des http:-Teils) des gewünschten Dokuments anzugeben.

Sie können auch benannte Argumente verwenden:

print $query->redirect(-uri=>'http://somewhere.else/in/movie/land',
                    -nph=>1);

Wird der Parameter -nph auf wahr gesetzt, werden die für ein NPH-Skript ("no-parse-header") benötigten Header generiert. Das ist in Verbindung mit bestimmten Servern besonders wichtig, etwa dem Microsoft Internet Explorer, weil diese erwarten, daß alle Skripten NPH-Skripten sind.

Erzeugung des HTML-Dokument-Headers

print $query->start_html(-title=>'Secrets of the Pyramids',
                         -author=>'fred@capricorn.org',
                         -base=>'true',
                         -target=>'_blank',
                         -meta=>{'keywords'=>'pharaoh secret mummy',
                                 'copyright'=>'copyright 1996 King Tut'},
                         -style=>{'src'=>'/styles/style1.css'},
                         -BGCOLOR=>'blue');

Nachdem der HTTP-Header erzeugt wurde, beginnen die meisten CGI-Skripten mit dem Absetzen eines HTML-Dokuments. Die Routine start_html() erzeugt den Anfang der Seite, zusammen mit vielen optionalen Informationen, die das Erscheinungsbild und das Verhalten der Seite bestimmen.

Die Methode liefert einen konservierten HTML-Header und den öffnenden <BODY>-Tag zurück. Alle Parameter sind optional. Als benannte Parameter werden -title, -author, -base, -xbase und -target (eine Erklärung finden Sie weiter unten) akzeptiert. Jeder zusätzliche Parameter, etwa das inoffizielle Netscape-Attribut BGCOLOR, wird dem <BODY>-Tag hinzugefügt. Zusätzlichen Parametern muß ein Bindestrich voranstehen.

Das Argument -xbase ermöglicht einen HREF für den <BASE>-Tag, der sich von der aktuellen Position unterscheidet:

-xbase=>"http://home.mcom.com/";

Alle relativen Links werden relativ zu diesem Tag interpretiert.

Das Argument -target erlaubt ein Standard-Ziel-Frame für alle Links und Formulare der Seite. Wie damit umzugehen ist, erläutert die Netscape-Dokumentation zu Frames.

-target=>"answer_window"

Alle relativen Links werden relativ zu diesem Tag interpretiert. Sie können willkürliche Metainformationen an den Header anhängen, indem Sie das Argument -meta verwenden. Dieses Argument erwartet einen Hash mit Name/Wert-Paaren, die die entsprechenden Metainformationen enthalten. Der Hash wird dann in eine Reihe von Header-<META>-Tags umgewandelt, die wie folgt aussehen:

<META NAME="keywords" CONTENT="pharaoh secret mummy">
<META NAME="description" CONTENT="copyright 1996 King Tut">

Der HTTP-EQUIV-Typ des <META>-Tags wird nicht unterstützt. Das liegt daran, daß Sie den HTTP-Header mit der header()-Methode direkt verändern können. Wenn Sie also beispielsweise den Refresh:-Header senden wollen, machen Sie das direkt mit der header()-Methode:

print $q->header(-Refresh=>'10; URL=http://www.capricorn.com');

Mit dem -style-Tag können Sie kaskadierende Stylesheets in Ihren Code einbinden. Weitere Informationen finden Sie im Abschnitt Eingeschränkte Unterstützung zur Kaskadierung von Stylesheets.

Sie können andere willkürliche HTML-Elemente in den <HEAD>-Abschnitt aufnehmen, indem Sie den -head-Tag benutzen. Um beispielsweise das recht selten verwendete <LINK>-Element in den Head-Abschnitt aufzunehmen, geben Sie folgendes ein:

print $q->start_html(-head=>Link({-rel=>'next',
                              -href=>'http://www.capricorn.com/s2.html'}));

Um mehrere HTML-Elemente in den <HEAD>-Abschnitt einzufügen, übergeben Sie einfach eine Arrayreferenz:

print $q->start_html(-head=>[ 
                          Link({-rel=>'next',
                                -href=>'http://www.capricorn.com/s2.html'}),
                          Link({-rel=>'previous',
                                -href=>'http://www.capricorn.com/s1.html'})
                         ]
                 );

JAVASCRIPTING: Die Parameter -script, -noScript, -onLoad, -onMouseOver, -onMouseOut und -onUnload werden verwendet, um Aufrufe von Netscapes JavaScript in Ihre Seiten einzufügen. -script muß auf einen Textblock verweisen, der JavaScript-Funktionsdefinitionen enthält. Dieser Block wird in einem <SCRIPT>-Block innerhalb des HTML-(nicht HTTP-)Headers plaziert. Der Block wird innerhalb des Headers plaziert, um Ihrer Seite eine reale Chance zu geben, alle JavaScript-Funktionen griffbereit zu haben, selbst wenn der Benutzer den Stop-Button drückt, bevor die Seite vollständig geladen wurde. CGI.pm versucht, das Skript so zu formatieren, daß selbst Browser, die JavaScript eher unbedarft gegenüberstehen, nicht über den Code stolpern. Unglücklicherweise gibt es einige Browser, etwa Chimera für Unix, die sich dennoch verwirren lassen.

Die Parameter -onLoad und -onUnload verweisen auf Fragmente mit JavaScript-Code, der ausgeführt werden soll, wenn der Browser die Seite öffnet bzw. schließt. Üblicherweise handelt es sich bei diesen Parametern um Aufrufe von Funktionen, die im -script-Feld definiert wurden:

$query = new CGI;
print $query->header;
$JSCRIPT=<<END;
// Alberne Frage fragen.
function riddle_me_this() {
   var r = prompt("Was geht morgens auf vier," +
                 "tagsüber auf zwei " +
                 "und abends auf drei Füßen?");
   response(r);
}
// Alberne Antwort einlesen.
function response(answer) {
   if (answer == "Mann")
      alert("Richtig!");
   else
      alert("Falsch!  Versuchen Sie es erneut.");
}
END
print $query->start_html(-title=>'Das Rätsel der Sphinx',
                         -script=>$JSCRIPT);

Verwenden Sie den Parameter -noScript, um einen HTML-Text zu übergeben, der von Browsern ausgegeben wird, die kein JavaScript unterstützen (oder bei denen es deaktiviert ist).

Netscape 3.0 erkennt verschiedene Attribute im <SCRIPT>-Tag, darunter LANGUAGE und SRC. Letzteres ist besonders interessant, weil dieses Attribut es uns möglich macht, den JavaScript-Code in einer Datei bzw. einem CGI-Skript zu halten, statt jede Seite mit dem Quelltext belasten zu müssen. Um diese Attribute nutzen zu können, übergeben Sie eine HASH-Referenz an den -script-Parameter, die einen oder mehrere -language-, -src- oder -code-Einträge enthält:

print $q->start_html(-title=>'Das Rätsel der Sphinx',
                        -script=>{-language=>'JAVASCRIPT',
                        -src=>'/javascript/sphinx.js'}
               );

print $q->(-title=>'Das Rätsel der Sphinx',
              -script=>{-language=>'PERLSCRIPT'},
              -code=>'print "Hallo Welt!\n;"'
     );

Ein letztes Feature ermöglicht es Ihnen, mehrere <SCRIPT>-Abschnitte in den Header aufzunehmen. Übergeben Sie die Liste der Skriptabschnitte einfach als Arrayreferenz. Damit können Sie unterschiedliche Quelldateien für verschiedene JavaScript-Dialekte festlegen:

print $q-&gt;start_html(-title=&gt;'Das Rätsel der Sphinx',
                     -script=&gt;[
                               { -language =&gt; 'JavaScript1.0',
                                 -src      =&gt; '/javascript/utilities10.js'
                               },
                               { -language =&gt; 'JavaScript1.1',
                                 -src      =&gt; '/javascript/utilities11.js'
                               },
                               { -language =&gt; 'JavaScript1.2',
                                 -src      =&gt; '/javascript/utilities12.js'
                               },
                               { -language =&gt; 'JavaScript28.2',
                                 -src      =&gt; '/javascript/utilities219.js'
                               }
                            ]
                        );

Wenn Ihnen das etwas zu extrem erscheint, nehmen Sie einen Rat von mir an und bleiben Sie bei reinen CGI-Skripten.

Weitere Informationen zu JavaScript finden Sie unter:

http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/

Die althergebrachten Parameter sind wie folgt:

  • Der Titel
  • Die E-Mail-Adresse des Autors (generiert, wenn vorhanden, einen <LINK REV="MADE">-Tag)
  • Eine 'true'-Flag, wenn Sie einen <BASE>-Tag in den Header aufnehmen wollen. Hilft bei der Auflösung relativer Adressen in absolute Adressen, wenn die Dokumente verschoben werden - macht die Dokumenthierarchie aber nicht portierbar. Mit Vorsicht anzuwenden!
  • Alle anderen Parameter, die Sie im <BODY>-Tag aufnehmen möchten. Ein guter Ort, um Netscape-Erweiterungen wie Farben und Hintergrundmuster aufzunehmen.
  • Beendigung des HTML-Dokuments

    print $query->end_html

    Beendet ein HTML-Dokument durch Ausgabe des </BODY></HTML>-Tags.

    Erzeugung einer selbstreferenzierenden URL, die Zustandsinformationen bewahrt

    $myself = $query->self_url;
    print "<A HREF=$myself>Ich rede mit mir selbst.</A>";

    self_url() gibt eine URL zurück, die, wenn sie aktiviert wird, dieses Skript erneut aufruft. Alle Zustandsinformationen bleiben dabei erhalten. Dies ist am nützlichsten, wenn Sie innerhalb des Dokuments mit Hilfe interner Anker herumspringen wollen, ohne den aktuellen Inhalt von Formular(en) verlieren zu wollen. Der dazu nötige Trick ist im folgenden Beispiel zu sehen:

    $myself = $query->self_url;
    print "<A HREF=$myself#table1>Siehe Tabelle 1</A>";
    print "<A HREF=$myself#table2>Siehe Tabelle 2</A>";
    print "<A HREF=$myself#yourself>Siehe selbst</A>";

    Wenn Sie eine größere Kontrolle über die Rückgabe besitzen wollen, verwenden Sie statt dessen die url()-Methode.

    Sie können auch einen unverarbeiteten Query-String mit query_string() empfangen:

    $the_string = $query->query_string;

    Die URL des Skripts bestimmen

    $full_url      = $query->url();
    $full_url      = $query->url(-full=>1);  #alternative Syntax
    $relative_url  = $query->url(-relative=>1);
    $absolute_url  = $query->url(-absolute=>1);
    $url_with_path = $query->url(-path_info=>1);
    $url_with_path_and_query = $query->url(-path_info=>1,-query=>1);

    url() liefert die URL des Skripts in unterschiedlichen Formaten zurück. Ohne irgendwelche Argumente wird die vollständige URL, inklusive Host-Namen und Port-Nummer, zurückgegeben.

    http://your.host.com/path/to/script.cgi

    Sie können dieses Format mit den folgenden benannten Argumenten ändern:

    -absolute
    Wenn wahr, wird eine absolute URL erzeugt, z.B.
    /path/to/script.cgi
    -relative
    Erzeugt eine relative URL. Nützlich, wenn Sie Ihr Skript mit anderen Parametern erneut aufrufen wollen. Beispiel:
    script.cgi
    -full
    Erzeugt eine vollständige URL. Entspricht genau dem Aufruf ohne irgendwelche Argumente. Überschreibt die Argumente -relative und -absolute.
    -path (-path_info)
    Hängt die zusätzlichen Pfadinformationen an die URL an. Kann mit -full, -absolute oder -relative kombiniert werden. -path_info steht als Synonym zur Verfügung.
    -query (-query_string)
    Hängt den Query-String an die URL an. Kann mit -full, -absolute oder -relative kombiniert werden. -query_string steht als Synonym zur Verfügung.

    POST- und URL-Parameter verwenden

       $color = $query-&gt;url_param('color');

    Die param()-Methode wird immer den Inhalt des POSTing-Formulars zurückgeben und den Query-String von URL ignorieren. Um URL-Parameter zu erhalten, rufen Sie die Methode url_param() auf. Sie wird auf dieselbe Weise verwendet wie param(). Der Hauptunterschied besteht darin, daß sie das Lesen, aber nicht das Setzen der Parameter ermöglicht.

    Standard-HTML-Elemente erzeugen

    CGI.pm definiert allgemeine HTML-Kurzformmethoden für die meisten, wenn nicht für alle Tags von HTML 3 und HTML 4. HTML-Kurzformen sind nach einem einzelnen HTML-Element benannt und liefern ein HTML-Fragment zurück, das Sie ausgeben oder in jeder gewünschten Weise manipulieren können. Jede Kurzform gibt ein HTML-Codefragment zurück, das Sie an einen String anhängen, in einer Datei sichern oder einfach so ausgeben können, daß es direkt im Browser erscheint (der häufigste Fall).

    Das nachfolgende Beispiel zeigt die Verwendung der HTML-Methoden:

    $q = new CGI;
    print $q->blockquote(
                      "Vor vielen, vielen Jahren lebte auf der Insel",
                      $q->a({href=>"http://crete.org/";},"Kreta"),
                      "ein Minotaurus namens ",
                      $q->strong("Fred."),
                     ),
        $q->hr;

    Das führt zu folgendem HTML-Code (zur besseren Lesbarkeit wurden zusätzliche Zeilenvorschübe eingefügt):

    <blockquote>
    Vor vielen, vielen Jahren lebte auf der Insel
    <a HREF="http://crete.org/";>Kreta</a>  
    ein Minotaurus namens <strong>Fred.</strong> 
    </blockquote>
    <hr>

    Wenn Ihnen die Syntax zum Aufruf der HTML-Kurzformen nicht behagt, können Sie sie in Ihren Namensraum importieren und auf die Objektsyntax vollständig verzichten (mehr dazu im nächsten Abschnitt):

    use CGI ':standard';
    print blockquote(
       "Vor vielen, vielen Jahren lebte auf der Insel",
       a({href=>"http://crete.org/";},"Kreta"),
       "ein Minotaurus namens",
       strong("Fred."),
       ),
       hr;

    Argumente an HTML-Kurzformen übergeben

    Die HTML-Methoden akzeptieren null, ein oder mehrere Argumente. Ohne Angabe von Argumenten erhalten Sie einen einzelnen Tag:

    print hr;    #  <HR>

    Geben Sie ein oder mehrere String-Argument(e) an, werden diese durch Leerzeichen miteinander verkettet und zwischen dem öffnenden und dem schließenden Tag plaziert:

    print h1("Kapitel","1"); # <H1>Kapitel 1</H1>"

    Handelt es sich beim ersten Argument um eine Hashreferenz, werden die Schlüssel und Werte des assoziativen Arrays zu den Attributen des HTML-Tags:

    print a({-href=>'fred.html',-target=>'_new'},
       "Neuen Frame öffnen");
    
             <A HREF="fred.html",TARGET="_new">Neuen Frame öffnen</A>

    Wenn Sie es vorziehen, können Sie die Bindestriche vor den Attributnamen auch weglassen:

    print img {src=>'fred.gif',align=>'LEFT'};
    
            <IMG ALIGN="LEFT" SRC="fred.gif">

    Manchmal besitzt ein HTML-Tag-Attribut kein Argument. Zum Beispiel können geordnete Listen als COMPACT markiert werden. In diesem Fall sieht die Syntax vor, daß das Argument auf einen undefinierten String zeigt:

    print ol({compact=>undef},li('one'),li('two'),li('three'));

    Vor der CGI.pm-Version 2.41 war die Angabe eines leeren Strings (") als Attributargument gleichwertig mit der Angabe von undef. Das wurde geändert, um auch diejenigen zufriedenzustellen, die Tags der Form <IMG ALT=""> erzeugen wollen. Die beiden folgenden Codezeilen machen den Unterschied deutlich: img({alt=undef}) <IMG ALT> img({alt="}) <IMG ALT="">

    Die distributive Eigenschaft der HTML-Kurzformen

    Eine der starken Eigenschaften der HTML-Kurzformen ist ihr distributives Verhalten. Wenn Sie eine Referenz auf eine Liste als Argument übergeben, wird der Tag über jedes Element der Liste verteilt. Als Beispiel sei hier eine Möglichkeit aufgeführt, eine geordnete Liste zu generieren:

    print ul(
              li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']);
            );

    Dieses Beispiel führt zu folgender HTML-Ausgabe:

    <UL>
      <LI TYPE="disc">Sneezy</LI>
      <LI TYPE="disc">Doc</LI>
      <LI TYPE="disc">Sleepy</LI>
      <LI TYPE="disc">Happy</LI>
    </UL>

    Das ist für die Generierung von Tabellen besonders nützlich:

    print table({-border=>undef},
            caption('Wann sollten Sie Gemüse essen?'),
            Tr({-align=>CENTER,-valign=>TOP},
            [
               th(['Gemüse', 'Frühstück','Mittagessen','Abendessen']),
               td(['Tomaten' , 'nein', 'ja', 'ja']),
               td(['Broccoli' , 'nein', 'nein',  'ja']),
               td(['Zwiebeln'   , 'ja','ja', 'ja'])
            ]
            )
         );

    HTML-Kurzformen und die Interpolation von Listen

    Betrachten Sie das nachfolgende Codefragment:

    print blockquote(em('Hi'),'mom!'));

    Üblicherweise erhalten Sie den String zurück, den Sie wohl auch erwarten, nämlich:

    <BLOCKQUOTE><EM>Hi</EM> mom!</BLOCKQUOTE>

    Beachten Sie das Leerzeichen zwischen dem Element "Hi" und dem Element "mom!". CGI.pm fügt dieses zusätzliche Leerzeichen mit Hilfe der Array-Interpolation ein, die über die magische Variable $" kontrolliert wird. Manchmal wollen Sie dieses zusätzliche Leerzeichen aber nicht, beispielsweise wenn Sie eine Reihe von Grafiken ausrichten. In diesem Fall setzen Sie den Wert von $" einfach auf den Leer-String:

    {
       local($") = '';
       print blockquote(em('Hi'),'mom!'));
     }

    Ich empfehle Ihnen, den Code, wie hier gezeigt, in einen Block zu setzen. Anderenfalls gilt die Änderung von $" für den gesamten nachfolgenden Code, bis die Variable explizit zurückgesetzt wird.

    HTML-Kurzformen jenseits des Standards

    Einige wenige HTML-Tags folgen aus verschiedenen Gründen nicht dem Standardmuster.

    comment() generiert einen HTML-Kommentar (<!-- kommentar -->). Der Aufruf erfolgt auf folgende Weise:

    print comment('Hier ist mein Kommentar');

    Aufgrund von Konflikten mit in Perl integrierten Funktionen beginnen die folgenden Funktionen mit einem Großbuchstaben:

    Select
    Tr
    Link
    Delete

    Darüber hinaus haben start_html(), end_html(), start_form(), end_form(), start_multipart_form() und alle Formular-Tags ihre Besonderheiten. Beachten Sie hierzu die entsprechenden Abschnitte.

    Erzeugung von Formularen

    Allgemeiner Hinweis: Die verschiedenen Methoden zur Formulargenerierung liefern alle einen String an den Aufrufer zurück. Dieser String enthält den Tag oder die Tags, die das angeforderte Formularelement erzeugen. Sie sind dafür verantwortlich, daß diese Strings auch tatsächlich ausgegeben werden. Dieser Weg wurde gewählt, damit Sie formatierende Tags um die Formularelemente plazieren können.

    Noch ein Hinweis: Die für das Formular möglicherweise festgelegten Standardwerte werden nur beim ersten Aufruf des Skripts (wenn kein Query-String vorliegt) verwendet. Bei nachfolgenden Aufrufen des Skripts (wenn ein Query-String existiert) werden die vorangegangenen Werte verwendet, auch wenn die entsprechenden Felder leer sind.

    Wenn Sie den vorherigen Wert eines Feldes ändern wollen, haben Sie zwei Möglichkeiten:

    (1) Setzen Sie den Wert mit der param()-Methode.

    (2) Verwenden Sie den Parameter -override (Alias -force), ein neues Feature ab Version 2.15. Damit erzwingen Sie, daß der Standardwert benutzt wird, unabhängig davon, welcher Wert vorher verwendet wurde:

    print $query->textfield(-name=>'feldname',
                            -default=>'startwert',
                            -override=>1,
                            -size=>50,
                            -maxlength=>80);

    Und noch ein Hinweis: Standardmäßig werden die Texte und Label von Formularelementen entsprechend den HTML-Regeln geschützt ("Escaping"). Das bedeutet, Sie können unbesorgt "<HIER KLICKEN>" als Label für einen Button verwenden. Andererseits behindert das die Fähigkeit, spezielle HTML-Zeichensequenzen wie &Aacute;, in Ihre Felder aufzunehmen. Wenn Sie das automatische Escaping ausschalten wollen, müssen Sie unmittelbar nach Erzeugung eines CGI-Objekts die Methode autoEscape() mit einem "falsch"-Wert aufrufen:

    $query = new CGI;
    $query->autoEscape(undef);
                              

    Erzeugung eines Isindex-Tags

    print $query->isindex(-action=>$action);

    - oder -

    print $query->isindex($action);

    Gibt einen <ISINDEX>-Tag aus. Nicht gerade aufregend. Der Parameter -action gibt die URL des Skripts an, das die Query verarbeiten soll. Per Voreinstellung wird die Query mit dem aktuellen Skript verarbeitet.

    Anfang und Ende eines Formulars

    print $query->startform(-method=>$method,
                            -action=>$action,
                            -encodingtype=>$encoding);
      <... verschiedene Formularelemente ...>
    print $query->endform;

    - oder -

    print $query->startform($method,$action,$encoding);
      <... verschiedene Formularelemente ...>
    print $query->endform;

    startform() gibt einen <FORM>-Tag zurück, der optional zu der von Ihnen übergebenen Methode, Aktion und Formularcodierung ist. Voreingestellt sind:
    method: POST
    action: dieses Skript
    encodingtype: application/x-www-form-urlencoded

    endform() liefert den schließenden </FORM>-Tag zurück.

    Der Codierungstyp von startform() teilt dem Browser mit, wie die verschiedenen Felder des Formulars zu packen sind, bevor das Formular an den Server geschickt wird. Zwei Werte sind möglich:

    application/x-www-form-urlencoded
    Dies ist die ältere Codierungsart, die von allen Browsern vor Netscape 2.0 verwendet wird. Sie ist mit vielen CGI-Skripten kompatibel und eignet sich für kurze, Textdaten enthaltende Felder. Zu Ihrer Bequemlichkeit speichert CGI.pm den Namen dieses Codierungstyps in $CGI::URL_ENCODED.
    multipart/form-data
    Dies ist der neuere Codierungstyp, der mit Netscape 2.0 eingeführt wurde. Er eignet sich für Formulare mit sehr großen Feldern bzw. solchen Feldern, die für die Übertragung binärer Daten gedacht sind. Wichtiger ist aber, daß es die Möglichkeit des Datei-Uploads von Netscape-2.0-Formularen unterstützt. Zu Ihrer Bequemlichkeit speichert CGI.pm den Namen dieses Codierungstyps in &CGI::MULTIPART
    Formulare, die diesen Codierungstyp verwenden, sind nicht so einfach von CGI-Skripten zu interpretieren, wenn Sie nicht mit CGI.pm oder einer anderen Bibliothek arbeiten, die die Verarbeitung dieses Typs erlaubt.

    Aus Kompatibilitätsgründen verwendet startform() per Voreinstellung die ältere Codierung. Wollen Sie standardmäßig mit der neueren Codierung arbeiten, können Sie start_multipart_form() anstelle von startform() aufrufen.

    JAVASCRIPTING: Die Parameter -name und -onSubmit stehen für die Arbeit mit JavaScript bereit. Der Parameter -name gibt dem Formular einen Namen, so daß es identifiziert und von JavaScript-Funktionen bearbeitet werden kann. -onSubmit muß auf eine JavaScript-Funktion zeigen, die ausgeführt wird, unmittelbar bevor das Formular an Ihren Server übertragen wird. Sie können diese Gelegenheit nutzen, um den Inhalt des Formulars auf Konsistenz und Vollständigkeit zu überprüfen. Falls Sie fehlerhafte Angaben entdecken, können Sie entweder eine Alarm-Box ausgeben oder die Dinge selbst korrigieren. Sie können die Übertragung abbrechen, indem Sie diese Funktion "falsch" zurückgeben lassen.

    Üblicherweise ist der Großteil der JavaScript-Funktionen in einem <SCRIPT>-Block des HTML-Headers definiert, und -onSubmit zeigt auf eine dieser Funktionen. Details finden Sie unter start_html().

    Erzeugung eines Textfeldes

    print $query->textfield(-name=>'feldname',
                            -default=>'startwert',
                            -size=>50,
                            -maxlength=>80);

    - oder -

    print $query->textfield('feldname','startwert',50,80);

    textfield() gibt ein Texteingabefeld zurück.

    Parameter
  • Der erste Parameter ist der für das Feld notwendige Name (-name).
  • Der zweite Parameter ist optional und enthält den Standardwert für den Feldinhalt (-default).
  • Der dritte Parameter ist optional und enthält die Größe des Feldes in Zeichen (-size).
  • Der vierte Parameter ist optional und enthält die maximale Anzahl von Zeichen, die in diesem Feld akzeptiert werden (-maxlength).
  • Wie bei all diesen Methoden wird das Feld mit dem Inhalt vorangegangener Aufrufe dieses Skripts initialisiert. Wird das Formular verarbeitet, kann der Wert des Textfeldes wie folgt ermittelt werden:

    $value = $query->param('foo');

    Soll nach dem Aufruf des Skripts der Standardwert wiederhergestellt werden, können Sie wie folgt vorgehen:

    $query->param('foo',"Ich verwende diesen Wert!");

    NEU SEIT VERSION 2.15: Soll das Feld nicht den vorherigen Wert annehmen, können Sie mit dem Parameter -override (Alias -force) die Verwendung des aktuellen Werts erzwingen:

    print $query->textfield(-name=>'feldname',
                            -default=>'startwert',
                            -override=>1,
                            -size=>50,
                            -maxlength=>80);

    JAVASCRIPTING: Sie können auch die Parameter -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut und -onSelect angeben, um JavaScript-Event-Handler einzurichten. Der Handler onChange wird immer dann aufgerufen, wenn der Benutzer den Inhalt des Textfeldes ändert. Bei Bedarf können Sie also die Validität des Textes prüfen. onFocus und onBlur werden aufgerufen, wenn der Zeiger in das bzw. aus dem Textfeld fährt. onSelect wird aufgerufen, wenn der Benutzer den markierten Textbereich ändert.

    Erzeugung eines großenTextfeldes

    print $query->textarea(-name=>'foo',
                           -default=>'startwert',
                           -rows=>10,
                           -columns=>50);

    -oder

    print $query->textarea('foo','startwert',10,50);

    textarea() ist wie textfield, erlaubt aber die Angabe von Spalten und Zeilen für ein mehrzeiliges Texteingabefeld. Sie können auch einen Standardwert für dieses Feld definieren, das lang sein und mehrere Zeilen einnehmen kann.

    JAVASCRIPTING: Die Parameter -onChange, -onFocus, -onBlur , -onMouseOver, -onMouseOut und -onSelect werden erkannt. Siehe textfield().

    Erzeugung eines Passwortfeldes

    print $query->password_field(-name=>'secret',
                                 -value=>'startwert',
                                 -size=>50,
                                 -maxlength=>80);

    - oder -

    print $query->password_field('secret','startwert',50,80);

    password_field() entspricht textfield(), nur daß die Zeichen auf der Web-Seite als Sternchen erscheinen.

    JAVASCRIPTING: Die Parameter -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut und -onSelect werden erkannt. Siehe textfield().

    Erzeugung eines Datei-Upload-Feldes

    print $query->filefield(-name=>'uploaded_file',
                            -default=>'startwert',
                            -size=>50,
                            -maxlength=>80);

    - oder -

    print $query->filefield('uploaded_file','startwert',50,80);

    filefield() gibt ein Datei-Upload-Feld für Netscape-2.0-Browser zurück. Um diese Fähigkeit vollständig nutzen zu können, müssen Sie die neue Multipart-Codierung für das Formular verwenden. Hierzu rufen Sie startform() entweder mit dem Codierungstyp $CGI::MULTIPART auf, oder Sie verwenden die neue Methode start_multipart_form() anstelle des üblichen startform()-Aufrufs.

    Parameter
  • Der erste Parameter ist der für das Feld notwendige Name (-name).
  • Der zweite Parameter ist optional und enthält den Standardwert für den Feldinhalt (-default).
  • Die Beta2-Version von Netscape 2.0 achtet nicht auf dieses Feld, weshalb das Feld immer leer ist. Schlimmer noch, das Feld verliert sein "anhängliches" Verhalten und vergißt seinen vorherigen Inhalt. Allerdings verlangt die HTML-Spezifikation das Standardwertfeld, d.h., noch folgende Netscape-Versionen werden es möglicherweise beachten.
  • Der dritte Parameter ist optional und enthält die Größe des Feldes in Zeichen (-size).
  • Der vierte Parameter ist optional und enthält die maximale Anzahl von Zeichen, die in diesem Feld akzeptiert werden (-maxlength).
  • Bei der Verarbeitung des Formulars können Sie den eingegebenen Dateinamen wie folgt mit param() ermitteln:

    $filename = $query->param('uploaded_file');

    Beim Netscape Navigator 2.0 entspricht der zurückgelieferte Dateiname dem lokalen Dateinamen auf der Maschine des Benutzers. Sitzt der entfernte Benutzer an einer Unix-Maschine, folgt der Dateiname den Unix-Konventionen:

    /path/to/the/file

    Bei MS-DOS/Windows- und OS/2-Maschinen folgt der Dateiname den DOS-Konventionen:

    C:\PATH\TO\THE\FILE.MSW

    Auf einem Macintosh-Rechner folgt der Dateiname den Mac-Konventionen:

    HD 40:Desktop Folder:Sort Through:Reminders

    Der zurückgegebene Dateiname ist gleichzeitig ein Dateihandle. Sie können den Inhalt der Datei mit gewöhnlichen Perl-Dateioperationen verarbeiten:

    # Textdatei lesen und ausgeben.
    while (<$filename>) {
       print;
    }
    
    # Binärdatei an einen sicheren Ort kopieren.
    open (OUTFILE,">>/usr/local/web/users/feedback");
    while ($bytesread=read($filename,$buffer,1024)) {
       print OUTFILE $buffer;
    }

    Findet ein Datei-Upload statt, sendet der Browser üblicherweise einige Informationen in Form von Headern mit. Diese Informationen umfassen üblicherweise den MIME-Inhaltstyp. Zukünftige Browser könnten noch zusätzliche Informationen (etwa das Modifikationsdatum) übergeben. Um an diese Informationen zu gelangen, rufen Sie uploadInfo() auf. Dies liefert eine Referenz auf ein assoziatives Array zurück, in dem alle Dokument-Header enthalten sind.

    $filename = $query->param('uploaded_file');
    $type = $query->uploadInfo($filename)->{'Content-Type'};
    unless ($type eq 'text/html') {
       die "NUR HTML-DATEIEN!";
    }

    Wenn Sie mit einer Maschine arbeiten, die "Text"- und "Binär"-Modi unterscheidet, sollten Sie ganz genau verstehen, wann und wie sie zu verwenden sind (schauen Sie im Kamel-Buch nach). Anderenfalls könnten Binärdateien bei Uploads beschädigt werden.

    JAVASCRIPTING: Die Parameter -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut und -onSelect werden erkannt. Siehe textfield().

    Erzeugung eines Popup-Menüs

    print $query->popup_menu('menu_name',
                             ['eenie','meenie','minie'],
                             'meenie');

    - oder -

    %labels = ('eenie'=>'erste Wahl',
               'meenie'=>'zweite Wahl',
               'minie'=>'dritte Wahl');
    print $query->popup_menu('menu_name',
                             ['eenie','meenie','minie'],
                             'meenie',\%labels);

    - oder (mit benannten Parametern) -

    print $query->popup_menu(-name=>'menu_name',
                             -values=>['eenie','meenie','minie'],
                             -default=>'meenie',
                             -labels=>\%labels);
    

    popup_menu() erzeugt ein Menü.

    Parameter:
  • Das erste Argument enthält den für das Menü notwendigen Namen (-name).
  • Das zweite Argument (-values) wird verlangt und ist eine Arrayreferenz, die auf die Liste der Menüelemente verweist. Sie können, wie im Beispiel gezeigt, ein anonymes Array übergeben oder ein benanntes Array wie "\@foo" referenzieren.
  • Der dritte Parameter (-default) ist optional und enthält den Namen des per Voreinstellung aktiven Menüpunkts. Wird der Parameter nicht angegeben, wird der erste Menüpunkt verwendet. Die Werte vorangegangener Entscheidungen bleiben über Queries hinweg erhalten.
  • Der vierte Parameter (-labels) ist optional und ist für Leute gedacht, die unterschiedliche Werte für die dem Benutzer innerhalb des Menüs vorgestellten Label und die vom Skript zurückgelieferten Werte verwenden möchten. Es handelt sich um einen Zeiger auf ein assoziatives Array, das Menüwerte auf Benutzer-Label abbildet. Lassen Sie diesen Parameter leer, werden standardmäßig die Menüwerte ausgegeben. (Wenn Sie möchten, können Sie ein Label auch undefiniert lassen.)
  • Bei der Verarbeitung des Formulars kann der im Popup-Menü gewählte Wert wie folgt ermittelt werden:

    $popup_menu_value = $query->param('menu_name');

    JAVASCRIPTING: popup_menu() erkennt die folgenden Event-Handler: -onChange, -onFocus, -onMouseOver, -onMouseOut und -onBlur. Details zum Aufruf dieser Handler finden Sie im Abschnitt über textfield().

    Erzeugung einer Scroll-Liste

    print $query->scrolling_list('list_name',
                                 ['eenie','meenie','minie','moe'],
                                 ['eenie','moe'],5,'true');

    - oder -

    
    print $query->scrolling_list('list_name',
                                 ['eenie','meenie','minie','moe'],
                                 ['eenie','moe'],5,'true',
                                 \%labels);

    - oder -

    
    print $query->scrolling_list(-name=>'list_name',
                                 -values=>['eenie','meenie','minie','moe'],
                                 -default=>['eenie','moe'],
                                 -size=>5,
                                 -multiple=>'true',
                                 -labels=>\%labels);

    scrolling_list() erzeugt eine Scroll-Liste.

    Parameter:
  • Das erste und das zweite Argument bilden den Listennamen (-name) sowie die Werte (-values) der Liste. Wie beim Popup-Menü muß das zweite Argument eine Arrayreferenz sein.
  • Das dritte Argument (-default) ist optional und kann entweder eine Referenz auf eine Liste mit Standardwerten oder ein einzelner Standardwert sein. Fehlt das Argument oder ist es undefiniert, dann ist beim ersten Erscheinen der Liste nichts markiert. In der Variante mit benannten Parametern können Sie das Synonym "-defaults" für diesen Parameter verwenden.
  • Das vierte Argument ist optional und gibt die Größe der Liste an (-size).
  • Das fünfte Argument ist optional und kann auf wahr gesetzt werden, um mehrere Selektionen gleichzeitig zu erlauben (-multiple). Anderenfalls ist nur jeweils eine Selektion erlaubt.
  • Das sechste Argument ist optional und enthält einen Zeiger auf ein assoziatives Array, das lange, für den Benutzer sichtbare Label für die Listenelemente enthält (-labels). Fehlt dieses Argument, werden die normalen Werte ausgegeben.
  • Bei der Verarbeitung des Formulars werden alle gewählten Elemente in Form einer Liste unter dem Parameternamen 'list_name' zurückgegeben. Die Werte der markierten Elemente können wie folgt bestimmt werden:

    @selected = $query->param('list_name');

  • JAVASCRIPTING: scrolling_list() erkennt die folgenden Event-Handler: -onChange, -onFocus, -onMouseOver, -onMouseOut und -onBlur. Wann diese Handler aufgerufen werden, wird im Abschnitt zu textfield() erklärt.

    Erzeugung einer Gruppe zusammengehöriger Kontrollkästchen

    print $query->checkbox_group(-name=>'group_name',
                                 -values=>['eenie','meenie','minie','moe'],
                                 -default=>['eenie','moe'],
                                 -linebreak=>'true',
                                 -labels=>\%labels);
    
    print $query->checkbox_group('group_name',
                                 ['eenie','meenie','minie','moe'],
                                 ['eenie','moe'],'true',\%labels);

    NUR BEI HTML3-KOMPATIBLEN BROWSERN:

    print $query->checkbox_group(-name=>'group_name',
                                 -values=>['eenie','meenie','minie','moe'],
                                 -rows=2,-columns=>2);
     

    checkbox_group() erzeugt eine Liste von Kontrollkästchen, die unter dem gleichen Namen zusammengefaßt sind.

    Parameter:
  • Das erste und das zweite Argument enthalten den Namen der Kontrollkästchen sowie die Werte (-name und -values). Wie beim Popup-Menü muß das zweite Argument eine Arrayreferenz sein. Die Werte erscheinen in der Ausgabe neben den Kontrollkästchen, bilden gleichzeitig aber auch die Werte, die Ihrem Skript im Query-String übergeben werden.
  • Das dritte Argument (-default) ist optional und kann entweder eine Referenz auf eine Liste mit aktiven Standardwerten oder ein einzelner aktiver Standardwert sein. Fehlt das Argument oder ist es undefiniert, dann ist beim ersten Erscheinen der Liste kein Element aktiv.
  • Das vierte Argument (-linebreak) ist optional und kann auf wahr gesetzt werden, um Zeilenumbrüche zwischen den Kontrollkästchen zu plazieren. Auf diese Weise erscheinen sie in Form einer vertikalen Liste. Anderenfalls werden sie auf einer horizontalen Linie zusammengefaßt.
  • Das fünfte Argument ist optional und enthält einen Zeiger auf ein assoziatives Array, das für den Benutzer sichtbare Label für die Kontrollkästchen enthält (-labels). Fehlt dieses Argument, werden die normalen Werte ausgegeben.
  • HTML3-kompatible Browser (wie Netscape) können die optionalen Parameter -rows und -columns nutzen. Mit Hilfe dieser Parameter liefert checkbox_group() eine HTML3-kompatible Tabelle zurück, in der die Gruppe der Kontrollkästchen mit der angegebenen Anzahl von Zeilen und Spalten aufbereitet ist. Wenn Sie wollen, können Sie auch nur den Parameter -columns angeben; checkbox_group berechnet dann die entsprechende Anzahl Zeilen für Sie.

    Um Zeilen- und Spaltenüberschriften in die zurückgelieferte Tabelle aufzunehmen, können Sie die Parameter -rowheaders und -colheaders verwenden. Beide erwarten einen Zeiger auf ein Array der zu verwendenden Überschriften. Diese Überschriften dienen nur der Dekoration. Eine Reorganisation der Kontrollkästchen findet nicht statt--sie bilden immer noch eine einzelne benannte Einheit.

  • Bei der Verarbeitung des Formulars werden alle aktivierten Kontrollkästchen in Form einer Liste unter dem Parameternamen 'group_name' zurückgegeben. Die Werte der aktiven Kontrollkästchen können wie folgt ermittelt werden:

    @turned_on = $query->param('group_name');

    Der von checkbox_group() zurückgegebene Wert ist tatsächlich ein Array von Button-Elementen. Sie können diese Elemente abfangen und in Tabellen, Listen oder auf andere kreative Weise einsetzen:

    @h = $query->checkbox_group(-name=>'group_name',-values=>\@values);
    &was_bin_ich_kreativ(@h);

    JAVASCRIPTING: checkbox_group() erkennt den Parameter -onClick. Dieser legt den JavaScript-Code bzw. die -Funktion fest, die aufgerufen wird, wenn der Benutzer einen Button der Gruppe anklickt. Sie können die Identität des jeweils angeklickten Buttons über die Variable "this" bestimmen.

    Erzeugung eines eigenständigen Kontrollkästchens

    print $query->checkbox(-name=>'checkbox_name',
                           -checked=>'checked',
                           -value=>'AN',
                           -label=>'KLICK MICH AN');

    - oder -

    print $query->checkbox('checkbox_name','checked','AN','KLICK MICH AN');

    checkbox() wird verwendet, um ein isoliertes Kontrollkästchen zu erzeugen, das nicht mit anderen verknüpft ist.

    Parameter:
  • Der erste Parameter enthält den für das Kontrollkästchen notwendigen Namen (-name). Gleichzeitig erscheint dieser Text als ein für den Benutzer sichtbares Label neben dem Kontrollkästchen.
  • Der zweite Parameter (-checked) ist optional und legt fest, ob das Kontrollkästchen standardmäßig aktiviert ist. Synonyme sind -selected und -on.
  • Der dritte Parameter (-value) ist optional und legt den Wert fest, den das Kontrollkästchen annimmt, wenn es aktiv ist. Wird kein Wert angegeben, wird das Wort "on" angenommen.
  • Der vierte Parameter (-label) ist optional und legt das für Benutzer im Kontrollkästchen sichtbare Label fest. Wird kein Wert angegeben, wird der Name des Kontrollkästchens verwendet.
  • Der Wert des Kontrollkästchens kann wie folgt ermittelt werden:

    $turned_on = $query->param('checkbox_name');

    JAVASCRIPTING: checkbox() erkennt den Parameter -onClick. Details hierzu finden Sie unter checkbox_group().

    Erzeugung einer Gruppe von Radio-Buttons

    print $query->radio_group(-name=>'group_name',
                              -values=>['eenie','meenie','minie'],
                              -default=>'meenie',
                              -linebreak=>'true',
                              -labels=>\%labels);

    - oder -

    print $query->radio_group('group_name',['eenie','meenie','minie'],
                                           'meenie','true',\%labels);

    NUR HTML3-KOMPATIBLE BROWSER:

    print $query->radio_group(-name=>'group_name',
                              -values=>['eenie','meenie','minie','moe'],
                              -rows=2,-columns=>2);

    radio_group() erzeugt einen Satz logisch zusammengehöriger Radio-Buttons. (Die Aktivierung eines Mitglieds der Gruppe deaktiviert alle anderen.)

    Parameter:
  • Das erste Argument enthält den Namen der Gruppe und wird verlangt (-name).
  • Das zweite Argument (-values) ist eine Liste mit Werten für die Radio-Buttons. Die Werte und die auf der Seite erscheinenden Labels sind identisch. Übergeben Sie eine Referenz auf ein Array im zweiten Argument. Die Referenz kann entweder auf ein anonymes Array (siehe oben) oder ein benanntes Array wie "\@foo" zeigen.
  • Der dritte Parameter (-default) ist optional und enthält den Namen des standardmäßig aktiven Buttons. Ohne diesen Parameter wird das erste Element aktiviert. Sie können auch einen nicht existierenden Button-Namen angeben, um ohne aktiven Button zu beginnen.
  • Der vierte Parameter (-linebreak) ist optional und kann auf wahr gesetzt werden, um Zeilenumbrüche zwischen den Buttons einzufügen, was zu einer vertikalen Liste führt.
  • Der fünfte Parameter (-label) ist optional und zeigt auf ein assoziatives Array, das die für die Benutzer im Radio-Button sichtbaren Label enthält. Wird kein Wert angegeben, werden die Werte selbst ausgegeben.
  • HTML3-kompatible Browser (wie Netscape) können die optionalen Parameter -rows und -columns nutzen. Mit Hilfe dieser Parameter liefert radio_group() eine HTML3-kompatible Tabelle zurück, in der die Gruppe der Radio-Buttons mit der angegebenen Anzahl von Zeilen und Spalten aufbereitet ist. Wenn Sie wollen, können Sie auch nur den Parameter -columns angeben; radio_group berechnet dann die entsprechende Anzahl Zeilen für Sie.

    Um Zeilen- und Spaltenüberschriften in die zurückgelieferte Tabelle aufzunehmen, können Sie die Parameter -rowheaders und -colheaders verwenden. Beide erwarten einen Zeiger auf ein Array der zu verwendenden Überschriften. Diese Überschriften dienen nur der Dekoration. Eine Reorganisation der Radio-Buttons findet nicht statt--sie bilden immer noch eine einzelne benannte Einheit.

  • Bei der Verarbeitung des Formulars kann der gewählte Radion-Button wie folgt ermittelt werden:

    $which_radio_button = $query->param('group_name');

    Der von radio_group() zurückgelieferte Wert ist tatsächlich ein Array mit Button-Elementen. Sie können diese Elemente abfangen und in Tabellen, Listen oder auf andere kreative Weise einsetzen:

    @h = $query->radio_group(-name=>'group_name',-values=>\@values);
    &was_bin_ich_kreativ(@h);

    Erzeugung eines Submit-Buttons

    print $query->submit(-name=>'button_name',
                         -value=>'value');

    - oder -

    print $query->submit('button_name','value');

    submit() erzeugt einen sogenannten Submit-Button zum Absenden einer Query. Jedes Formular muß einen solchen Button besitzen.

    Parameter:
  • Das erste Argument (-name) ist optional. Sie können dem Button einen Namen geben, wenn Ihr Formular mehrere dieser Buttons besitzt und Sie diese unterscheiden wollen. Der Name wird gleichzeitig als für den Benutzer sichtbares Label verwendet. Beachten Sie, daß einige ältere Browser damit nicht richtig umgehen können und nie einen Wert vom Button zurückgeben.
  • Das zweite Argument (-value) ist ebenfalls optional. Es weist dem Button einen Wert zu, der Ihrem Skript im Query-String übergeben wird.
  • Sie können ermitteln, welcher Button gedrückt wurde, indem Sie jedem Button einen anderen Wert zuweisen:

    $which_one = $query->param('button_name');

    JAVASCRIPTING: radio_group() erkennt den Parameter -onClick. Details hierzu finden Sie unter checkbox_group().

    Erzeugung eines Reset-Buttons

    print $query->reset

    reset() erzeugt den "Reset"-Button. Beachten Sie, daß das Formular auf die Werte zurückgesetzt wird, die beim letzten Aufruf des Skripts verwendet wurden, NICHT notwendigerweise auf die Standardwerte.

    Erzeugung eines Default-Buttons

    print $query->defaults('button_label')

    defaults() erzeugt einen Button, der beim Aufruf das gesamte Formular auf seine Standardwerte zurücksetzt und so alle bislang durchgeführten Änderungen verwirft.

    Erzeugung eines versteckten Feldes

    print $query->hidden(-name=>'hidden_name',
                         -default=>['value1','value2'...]);

    - oder -

    print $query->hidden('hidden_name','value1','value2'...);

    hidden() erzeugt ein Textfeld, das für den Benutzer unsichtbar ist. Es ist nützlich für die Übergabe von Zustandsinformationen von einem Aufruf des Skripts zum nächsten.

    Parameter:
  • Das erste Argument ist notwendig und legt den Namen dieses Feldes fest (-name).
  • Das zweite Argument wird ebenfalls verlangt und legt den Wert fest (-default). Beim Aufruf mit benannten Parametern können Sie hier einen einzelnen Wert oder eine Referenz auf eine ganze Liste angeben.
  • Den Wert eines versteckten Feldes bestimmen Sie wie folgt:

    $hidden_value = $query->param('hidden_name');

    Beachten Sie, daß, genau wie bei allen anderen Formularelementen, der Wert eines versteckten Feldes sehr "anhänglich" ("sticky") ist. Möchten Sie den Wert eines versteckten Feldes ändern, nachdem das Skript einmal aufgerufen wurde, müssen Sie das manuell erledigen.

    $query->param('hidden_name','new','values','here');

    Erzeugung eines Clickable-Image-Buttons

    print $query->image_button(-name=>'button_name',
                               -src=>'/source/URL',
                               -align=>'MIDDLE');      

    - oder -

    print $query->image_button('button_name','/source/URL','MIDDLE');

    image_button() erzeugt ein sogenanntes "clickable Image". Beim Anklicken des Images wird die Position des Klicks im Format "button_name.x" und "button_name.y" an Ihr Skript zurückgeliefert. "button_name" ist dabei der von Ihnen zugewiesene Name.

    JAVASCRIPTING: image_button() erkennt den Parameter -onClick. Details finden Sie unter checkbox_group().

    Parameter:
  • Das erste Argument (-name) wird verlangt und legt den Namen dieses Feldes fest.
  • Das zweite Argument (-src) wird ebenfalls verlangt und gibt die URL an.
  • Das dritte Argument (-align) ist optional und legt die Ausrichtung (TOP, BOTTOM oder MIDDLE) fest.
  • Die Koordinaten bestimmen Sie wie folgt: $x = $query->param('button_name.x'); $y = $query->param('button_name.y');

    Erzeugung eines Javascript-Action-Buttons

    print $query->button(-name=>'button_name',
                         -value=>'Label_fuer_Benutzer',
                         -onClick=>"tu_was()");

    - oder -

    print $query->button('button_name',"tu_was()");

    button() erzeugt einen Button, der zum Netscape-2.0-JavaScript kompatibel ist. Beim Anklicken wird der JavaScript-Code ausgeführt, auf den der Parameter -onClick verweist. Bei Nicht-Netscape-Browsern erscheint dieses Formularelement möglicherweise gar nicht erst.

    Netscape-Cookies

    Netscape-Browser unterstützen seit der Version 1.1 sogenannte "Cookies", die den Zustand innerhalb einer Browser-Session verwalten helfen. CGI.pm besitzt verschiedene Methoden zur Unterstützung von Cookies.

    Ein Cookie ist ein Name/Wert-Paar, das den benannten Parametern in einem CGI-Query-String sehr ähnlich ist. CGI-Skripten erzeugen ein oder mehrere Cookies und senden diese im HTTP-Header an den Browser. Der Browser pflegt eine Liste von Cookies, getrennt nach Web-Servern, und liefert sie während nachfolgender Interaktionen an das CGI-Skript zurück.

    Neben dem notwendigen Name/Wert-Paar besitzt jedes Cookie verschiedene optionale Attribute:

    1. ein Ablaufdatum: Ein Zeit/Datum-String (in einem besonderen GMT-Format), der angibt, wann das Cookie ungültig wird. Das Cookie wird gespeichert und an das Skript zurückgegeben, bis das Ablaufdatum erreicht ist - auch wenn der Benutzer Netscape beendet und erneut startet. Wird kein Ablaufdatum festgelegt, bleibt das Cookie aktiv, bis der Benutzer Netscape beendet.
    2. eine Domain: Ein (möglicherweise vollständiger) Domain-Name, für den das Cookie gültig ist. Der Browser gibt das Cookie an jeden Host zurück, der den partiellen Host-Namen besitzt. Haben Sie zum Beispiel den Domain-Namen ".capricorn.com" angegeben, gibt Netscape das Cookie an Web-Server zurück, die auf Maschinen wie "www.capricorn.com", "www2.capricorn.com", "feckless.capricorn.com" etc. laufen. Domain-Namen müssen mindestens zwei Punkte enthalten, um Treffer auf Top-Level-Domains wie ".edu" zu verhindern. Wird keine Domain festgelegt, gibt der Browser das Cookie nur an Server auf dem Host zurück, von dem das Cookie stammt.
    3. einen Pfad: Geben Sie ein Pfadattribut an, prüft der Browser zuerst die URL des Skripts, bevor er das Cookie zurückliefert. Geben Sie beispielsweise den Pfad "/cgi-bin" an, wird das Cookie an die Skripten "/cgi-bin/tally.pl", "/cgi-bin/order.pl" und "/cgi-bin/customer_service/complain.pl", nicht aber an das Skript "/cgi-private/site_admin.pl", zurückgegeben. Standardmäßig ist der Pfad auf "/" gesetzt, d.h., das Cookie wird an jedes CGI-Skript Ihrer Site übertragen.
    4. eine "secure"-Flag: Ist das "secure"-Attribut gesetzt, wird das Cookie nur an Ihr Skript übertragen, wenn der CGI-Request über einen sicheren Kanal, etwa SSL, erfolgt.

    Die Schnittstelle zu Netscape-Cookies bildet die cookie()-Methode:

    $cookie = $query->cookie(-name=>'sessionID',
                             -value=>'xyzzy',
                             -expires=>'+1h',
                             -path=>'/cgi-bin/database',
                             -domain=>'.capricorn.org',
                             -secure=>1);
    print $query->header(-cookie=>$cookie);

    cookie() erzeugt ein neues Cookie. Die Parameter sind:

    -name
    Der Name des Cookies (notwendig). Kann ein beliebiger String sein. Obwohl Netscape die Namen von Cookies auf alphanumerische Zeichen ohne Whitespace einschränkt, hebt CGI.pm diese Beschränkung auf, indem es hinter den Kulissen entsprechende Fluchtsequenzen einfügt bzw. entfernt.
    -value
    Der Wert des Cookies. Dies kann ein beliebiger Skalarwert, eine Arrayreferenz oder auch eine Hashreferenz sein. Zum Beispiel können Sie ein ganzes assoziatives Array wie folgt in einem Cookie ablegen:
    $cookie=$query->cookie(-name=>'family information',
                           -value=>\%childrens_ages);
    -path
    Der optionale partielle Pfad (wie oben beschrieben), für den das Cookie gültig ist.
    -domain
    Die optionale partielle Domain (wie oben beschrieben), für die das Cookie gültig ist.
    -expires
    Das optionale Ablaufdatum dieses Cookies. Das Format wird im Abschnitt über die header()-Methode beschrieben:
    "+1h"  in einer Stunde von nun an
    -secure
    Auf wahr gesetzt, wird das Cookie nur innerhalb einer sicheren SSL-Session verwendet.

    Das von cookie() erzeugte Cookie muß innerhalb des durch die header()-Methode zurückgelieferten Strings in den HTTP-Header eingebunden werden:

    print $query->header(-cookie=>$my_cookie);

    Um mehrere Cookies zu erzeugen, übergeben Sie header() eine Arrayreferenz:

    $cookie1 = $query->cookie(-name=>'riddle_name',
                                 -value=>"Die Frage der Sphinx");
    $cookie2 = $query->cookie(-name=>'answers',
                                 -value=>\%answers);
    print $query->header(-cookie=>[$cookie1,$cookie2]);

    Um ein Cookie zu ermitteln, rufen Sie cookie() mit dem entsprechenden Namen, aber ohne den -value-Parameter, auf:

    use CGI;
    $query = new CGI;
    %answers = $query->cookie(-name=>'answers');
    # $query->cookie('answers') funktioniert auch!

    Cookies und CGI besitzen getrennte Namensräume. Besitzen Sie einen Parameter namens 'answers' und ein Cookie namens 'answers', sind die durch param() und cookie() zurückgelieferten Werte völlig unabhängig voneinander. Dennoch ist es einfach, einen CGI-Parameter in ein Cookie (und umgekehrt) umzuwandeln:

    # CGI-Parameter in Cookie umwandeln.
    $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
    # Cookie in CGI-Parameter umwandeln.
    $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);

    Einige Ideen zur effektiven Nutzung von Cookies finden Sie im Beispielskript cookie.cgi.

    Hinweis: Für Netscape-Cookies seien einige (undokumentierte) Einschränkungen genannt. Zumindest unter Netscape 2.01 ist es mir nicht gelungen, mehr als drei Cookies gleichzeitig zu setzen. Auch was die Länge der Cookies angeht, könnte es Beschränkungen geben. Wenn Sie viele Informationen speichern müssen, ist es wahrscheinlich besser, eine eindeutige Session-ID zu erzeugen, diese in einem Cookie abzulegen und dann die ID zu benutzen, um auf eine externe Datei/Datenbank zuzugreifen, die direkt auf dem Server liegt.

    Arbeiten mit Netscape-Frames

    Es ist CGI.pm-Skripten mit Hilfe des Frame-Mechanismus von Netscape möglich, in verschiedene Browser-Panels und -Fenster zu schreiben. Drei verschiedene Techniken stehen zur Definition neuer Frames zur Verfügung:

    1. Erzeugen eines <FRAMESET>-Dokuments: Nach dem Schreiben des HTTP-Headers erzeugen Sie, statt mit start_html() ein Standard-HTML-Dokument zu generieren, ein <FRAMESET>-Dokument, das die Frames der Seite definiert. Geben Sie Ihr(e) Skript(en) (mit den entsprechenden Parametern) im SRC-Tag jedes Frames an.
    2. Es gibt bei CGI.pm keine besondere Unterstützung für die Erzeugung von <FRAMESET>-Abschnitten, der notwendige HTML-Code ist aber sehr einfach zu schreiben. Details finden Sie in der Frame-Dokumentation auf der Netscape-Homepage:

      http://home.netscape.com/assist/net_sites/frames.html
    3. Angabe des Ziels im HTTP-Header: Sie können einen -target-Parameter in der header()-Methode übergeben:
      print $q->header(-target=>'Ergebnisfenster');
      Damit weisen Sie Netscape an, die Ausgabe Ihres Skripts an den Frame namens "Ergebnisfenster" zu schicken. Wenn ein Frame dieses Namens noch nicht existiert, öffnet Netscape ein neues Fenster und gibt das von Ihrem Skript erzeugte Dokument in diesem Fenster aus. Es gibt eine Reihe "magischer" Namen, die Sie als Ziel angeben können. Auch hierzu finden Sie die genauen Details in den Frame-Dokumenten auf den Netscape-Homepages.
    4. Angabe des Ziels im <FORM>-Tag: Sie können den zu verwendenden Frame auch im FORM-Tag selbst angeben. Mit CGI.pm sieht das folgendermaßen aus:
      print $q->startform(-target=>'Ergebnisfenster');
      Wird Ihr Skript vom Formular erneut aufgerufen, geht die Ausgabe an den Frame namens "Ergebnisfenster". Existiert der Frame noch nicht, wird ein neues Fenster erzeugt.

    Das Skript "frameset.cgi" im Beispielverzeichnis zeigt eine Möglichkeit, bei der ein Formular und die Antwort in nebeneinanderliegenden Frames existieren.

    Eingeschränkte Unterstützung zur Kaskadierung von Stylesheets

    CGI.pm unterstützt eingeschränkt Cascading Style Sheets (CSS, kaskadenartige Formatvorlagen) von HTML 3. Um ein Stylesheet in Ihr Dokument einzubinden, übergeben Sie der start_html()-Methode den Parameter -style. Der Wert dieses Parameters kann ein Skalar sein, was zu einer direkten Einbettung in einen <STYLE>-Abschnitt führt, es kann aber auch eine Hashreferenz übergeben werden. In letzterem Fall müssen Sie den Hash mit einer oder mehreren -src- oder -code-Angaben versehen. -src zeigt auf eine URL, auf der ein extern definiertes Stylesheet zu finden ist. -code verweist auf einen Skalarwert, der im <STYLE>-Bereich einzubetten ist. Style-Definitionen in -code überschreiben gleichnamige Definitionen in -src, daher auch der Begriff "kaskadieren".

    Sie können auch den Typ des Stylesheets festlegen, indem Sie den optionalen -type-Parameter zum durch -style referenzierten Hash hinzufügen. Geben Sie den Typ nicht an, wird standardmäßig 'text/css' angenommen.

    Um auf einen Style innerhalb des Bodies Ihres Dokuments zu verweisen, fügen Sie jedem HTML-Element den Parameter -class hinzu:

    print h1({-class=>'Fancy'},'Willkommen zur Party');

    Oder definieren Sie Styles mit dem Parameter -style so nebenbei:

    print h1({-style=>'Color: red;'},'Willkommen in der Hölle');

    Sie können auch das neue span()-Element verwenden, um einen Style auf einen Textabschnitt anzuwenden:

    print span({-style=>'Color: red;'},
               h1('Willkommen in der Hölle'),
               "Wer ist jetzt dran?"
               );

    Beachten Sie, daß Sie die ":html3"-Definitionen importieren müssen, um die span()-Methode nutzen zu können. Hier folgt ein kleines Beispiel für die Verwendung von CSS. Weitere Informationen finden Sie in der CSS-Spezifikation unter http://www.w3.org.

    use CGI qw/:standard :html3/;
    
    #Ein direkt in die Seite eingebundenes Stylesheet
    $newStyle=<<END;
    <!-- 
    P.Tip {
        margin-right: 50pt;
        margin-left: 50pt;
        color: red;
    }
    P.Alert {
        font-size: 30pt;
        font-family: sans-serif;
      color: red;
    }
    -->
    END
    print header();
    print start_html( -title=>'CGI mit Stil',
                      -style=>{-src=>'http://www.capricorn.com/style/st1.css',
                               -code=>$newStyle}
                     );
    print h1('CGI mit Stil'),
          p({-class=>'Tip'},
            "Lesen Sie zuerst die CSS-Specs, bevor Sie hiermit rumspielen!"),
          span({-style=>'color: magenta'},
               "Schau mal Mutti, freihändig!",
               p(),
               "JuuHuuu!"
               );
    print end_html;

    Debugging

    Wenn Sie das Skript über die Kommandozeile oder mit dem Perl-Debugger ausführen, können Sie dem Skript in der Kommandozeile oder über die Standardeingabe eine Liste mit Schlüsselwörtern oder Parameter/Wert-Paaren übergeben. (Sie müssen also nicht mit Umgebungsvariablen tricksen.) Schlüsselwörter werden wie folgt übergeben:

    ihr_skript.pl schlüsselwort1 schlüsselwort2 schlüsselwort3

    oder so:

    ihr_skript.pl schlüsselwort1+schlüsselwort2+schlüsselwort3

    oder so:

    ihr_skript.pl name1=wert1 name2=wert2

    oder so:

    ihr_skript.pl name1=wert1&name2=wert2

    Sie können sogar durch Zeilenvorschübe getrennte Parameter über die Standardeingabe einlesen.

    Während des Debuggens können Sie in der für Shells üblichen Weise Quoting-Zeichen und Backslashes zum Schutz einzelner Zeichen verwenden. Damit können Sie Leerzeichen und andere Sonderzeichen in Ihre Parameter/Wert-Paare einfügen:

    ihr_skript.pl "name1='Ein sehr langer Wert'" "name2=zwei\ Worte"

    Ausgabe aller Name/Wert-Paare

    Die dump()-Methode erzeugt einen String, der alle Name/Wert-Paare der Query enthält. Diese Werte sind in Form einer verschachtelten Liste aufbereitet, was für Debugging-Zwecke sehr nützlich ist:

    print $query->dump

    Dies erzeugt so etwas wie:

    <UL>
    <LI>name1
        <UL>
        <LI>wert1
        <LI>wert2
        </UL>
    <LI>name2
        <UL>
        <LI>wert1
        </UL>
    </UL>

    Sie können dump() den Wert 'wahr' übergeben, was dazu führt, daß das Ergebnis als reiner Text zurückgegeben wird, der in einem <PRE>-Abschnitt eingebettet werden kann.

    Seit der Version 1.56 können Sie das gesamte CGI-Objekt in einen String interpolieren, der dann durch den oben gezeigten HTML-Dump ersetzt wird:

    $query=new CGI;
    print "<H2>Aktuelle Werte</H2> $query\n";

    Abfrage von Umgebungsvariablen

    Einige der sinnvolleren Umgebungsvariablen können durch diese Schnittstelle abgefragt werden. Folgende Methoden stehen zur Verfügung:

    accept()
    Gibt eine Liste aller vom entfernten Browser akzeptierten MIME-Typen zurück. Übergeben Sie der Methode ein einzelnes Argument, das einem MIME-Typ entspricht, beispielsweise $query->accept('text/html'), erhalten Sie einen Fließkommawert zurück, der die Präferenz des Browsers für diesen Typ widerspiegelt. Dieser Wert reicht von 0.0 (Typ ist nicht erwünscht) bis 1.0. Glob-Typen (z.B. text/*) in der Accept-Liste des Browsers werden korrekt verarbeitet.
    raw_cookie()
    Gibt die Variable HTTP_COOKIE zurück. Hierbei handelt es sich um eine HTTP-Erweiterung, die von Netscape-Browsern ab der Version 1.1 unterstützt wird. Cookies besitzen ein spezielles Format, und diese Methode gibt einfach das "rohe" Cookie zurück. Für das normale Arbeiten mit Cookies verwenden Sie cookie().
    Beim Aufruf ohne Parameter gibt raw_cookie() die gepackte Cookie-Struktur zurück. Eine Aufteilung in einzelne Cookies ist über eine Split-Operation mit der Zeichensequenz "; " möglich. Erfolgt der Aufruf mit dem Namen eines Cookies, wird die unverfälschte Form des Cookies zurückgegeben. Sie gelangen an die Namen mit der normalen cookie()-Methode oder mit Hilfe der raw_fetch()-Methode des CGI::Cookie-Moduls.
    user_agent()
    Liefert die Variable HTTP_USER_AGENT zurück. Übergeben Sie der Methode ein einzelnes Argument, wird eine Mustererkennung durchgeführt, was Dinge wie $query->user_agent(netscape); möglich macht.
    path_info()
    Gibt zusätzliche Pfadinformationen zur Skript-URL zurück. Beispielsweise wird bei /cgi-bin/your_script/additional/stuff von $query->path_info() der Wert "additional/stuff" zurückgegeben.
    HINWEIS: Der Microsoft Internet Information Server behandelt zusätzliche Pfadinformationen nicht richtig. Wenn Sie die Perl-DLL-Bibliothek verwenden, versucht der IIS-Server, die zusätzlichen Pfadinformationen als Perl-Skript auszuführen. Wenn Sie die normalen Abbildungen für Dateien verwenden, ist die Pfadinformation zwar in der Umgebung vorhanden, aber leider nicht korrekt. Am besten verzichten Sie ganz auf zusätzliche Pfadinformationen, wenn Sie CGI-Skripten für den IIS entwickeln.
    path_translated()
    Wie path_info(), wandelt die Pfadinformationen aber in einen physikalischen Pfad um, z.B. "/usr/local/etc/httpd/htdocs/additional/stuff".
    Auch den übersetzten Pfad kann der Microsoft IIS nicht richtig verarbeiten.
    remote_host()
    Gibt den Namen des entfernten Hosts zurück, oder dessen IP-Adresse, falls der Name nicht verfügbar ist.
    script_name() Gibt den Namen des Skripts in Form einer partiellen URL zurück. Nützlich bei selbstreferenzierenden Skripten.
    referer()
    Gibt die URL der Seite zurück, die im Browser betrachtet wurde, bevor auf Ihr Skript zugegriffen wurde. Nicht bei allen Browsern verfügbar.
    auth_type ()
    Gibt (falls vorhanden) die für dieses Skript verwendete Autorisierungs-/Verifikationsmethode zurück.
    server_name ()
    Gibt den Namen des Servers zurück, üblicherweise der Host-Name des Rechners.
    virtual_host ()
    Gibt bei virtuellen Hosts den Namen des Hosts zurück, auf den der Browser zugreifen wollte.
    server_software ()
    Gibt die Server-Software und die Versionsnummer zurück.
    remote_user ()
    Gibt den Autorisierungs-/Verifikationsnamen zurück, der bei einem geschützten Skript zur Benutzerverifikation verwendet wird.
    user_name ()
    Versucht über eine Reihe verschiedener Techniken den Namen des entfernten Benutzers zu ermitteln. Funktioniert nur mit älteren Browsern wie Mosaic. Netscape liefert den Benutzernamen nicht zuverlässig zurück!
    request_method()
    Gibt die Methode zurück, mit der auf Ihr Skript zugegriffen wurde. Üblicherweise 'POST', 'GET' oder 'HEAD'.

    Nutzung von NPH-Skripten

    NPH-Skripten ("no-parsed-header") umgehen den Server und senden den vollständigen HTTP-Header direkt an den Browser. Das bringt eine leichte Verbesserung im Durchsatz, ist aber am nützlichsten, um HTTP-Erweiterungen zu verwenden, die von Ihrem Server nicht direkt unterstützt werden (etwa Server-Push und PICS-Header).

    Server verwenden eine Reihe von Konventionen, um CGI-Skripten als NPH-Skripten zu kennzeichnen. Viele Unix-Server untersuchen den Anfang des Dateinamens auf das Präfix "nph-". Der WebSTAR-Server für den Macintosh und der Microsoft Internet Information Server hingegen versuchen anhand der ersten Zeile der Ausgabe zu entscheiden, ob es sich um ein NPH-Skript handelt.

    CGI.pm unterstützt NPH-Skripten durch einen speziellen NPH-Modus. In diesem Modus gibt CGI.pm beim Aufruf der header()- und redirect()-Methoden alle zusätzlich benötigten Header-Informationen aus.

    Der Microsoft Internet Information Server verlangt den NPH-Modus. Seit der Version 2.30 erkennt CGI.pm automatisch, ob ein Skript unter IIS läuft, und schaltet sich von selbst in diesen Modus. Sie müssen dies also nicht von Hand ausführen, auch wenn Sie damit keinen Schaden anrichten können.

    Es gibt eine Reihe von Möglichkeiten, CGI.pm in den NPH-Modus zu schalten:

    In der use-Anweisung:
    Fügen Sie einfach das Pragma "-nph" in die Symbolliste ein, die in Ihr Skript importiert werden soll.
    use CGI qw(:standard -nph)
    Durch Aufruf der nph()-Methode:
    Rufen Sie nph() mit einem Parameter ungleich null auf, nachdem Sie CGI.pm in Ihrem Programm verwendet haben.
    CGI->nph(1)
    Durch Nutzung von -nph-Parametern in header()- und redirect()-Anweisungen:
    print $q->header(-nph=>1);

    Server-Push

    CGI.pm stellt drei einfache Funktionen zur Verfügung, mit denen Multipart-Dokumente erzeugt werden können, die zur Implementierung eines Server-Pushes notwendig sind. Diese Funktionen wurden großzügigerweise von Ed Jordan ."<ed@fidalgo.net bereitgestellt. Um sie in Ihren Namensraum einzubinden, müssen Sie den ":push"-Satz importieren. Gleichzeitig ist es ratsam, das Skript in den NPH-Modus zu schalten und $| auf 1 zu setzen, um Probleme mit der Pufferung zu vermeiden.

    Hier ein einfaches Beispiel, das den Server-Push demonstriert:

    #!/usr/local/bin/perl
    use CGI qw/:push -nph/;
    $| = 1;
    print multipart_init(-boundary=>'----------------und los!');
    while (1) {
        print multipart_start(-type=>'text/plain'),
              "Die aktuelle Zeit ist ",scalar(localtime),"\n",
              multipart_end;
        sleep 1;
    }

    Das Skript initialisiert den Server-Push durch den Aufruf von multipart_init(). Danach tritt es in eine Endlosschleife ein, in der mit multipart_start() ein neuer Multipart-Abschnitt eingeleitet, die lokale Zeit ausgegeben und mit multipart_end() der Multipart-Abschnitt beendet wird. Danach wird eine Sekunde gewartet, bevor das Ganze von neuem beginnt.

    multipart_init() multipart_init(-boundary=$boundary);
    Initialisiert das Multipart-System. Das Argument -boundary legt den MIME-Boundary-String fest, mit dem die Teile des Dokuments getrennt werden. Geben Sie keinen String an, wählt CGI.pm einen für Sie aus.
    multipart_start()
    multipart_start(-type=>$type)
    Beginnt einen neuen Teil des Multipart-Dokuments mit dem angegebenen MIME-Typ. Wird der Typ nicht angegeben, geht CGI.pm von text/html aus.
    multipart_end()
    multipart_end()
    Beendet den Teil. Sie müssen multipart_end() für jedes multipart_start() einmal aufrufen.

    An Server-Push-Anwendungen interessierte Benutzer sollten sich auch das CGI::Push-Modul ansehen.

    "Denial of Service"-Attacken vermeiden

    Ein mögliches Problem von CGI.pm besteht darin, daß es standardmäßig versucht, Formular-POSTings unabhängig von ihrer Länge zu verarbeiten. Ein böser Hacker könnte Ihre Site angreifen, indem er einem CGI-Skript ein mehrere Megabyte großes POSTing schickt. CGI.pm wird versuchen, das gesamte POSTing in eine Variable einzulesen, die daraufhin sehr groß wird, bis möglicherweise sogar der Speicher aufgebraucht ist. Während das Skript versucht, den benötigten Speicher anzufordern, kann die Geschwindigkeit Ihres Systems dramatisch sinken. Das ist eine Form der sogenannten "Denial of Service"-Attacken.

    Eine andere Möglichkeit des Angriffs besteht darin, daß der entfernte Benutzer CGI.pm dazu bringt, einen sehr großen Datei-Upload zu akzeptieren. CGI.pm wird den Upload akzeptieren und ihn in einem temporären Verzeichnis unterbringen, selbst wenn das Skript eigentlich keinen Upload erwartet. CGI.pm löscht diese Datei beim Beenden zwar automatisch, aber in der Zwischenzeit könnte der entfernte Benutzer die Platte des Servers aufgefüllt haben und so bei anderen Programmen Probleme verursachen.

    Die beste Möglichkeit, Denial-of-Service-Angriffe zu vermeiden, besteht darin, den Speicher, die CPU-Zeit und den Plattenplatz für CGI-Skripten zu beschränken. Einige Web-Server besitzen Möglichkeiten, um so etwas zu erreichen. In anderen Fällen können Sie die Shell-Befehle limit oder ulimit verwenden, um Obergrenzen für CGI-Ressourcen festzulegen.

    CGI.pm besitzt auch einige einfache, fest integrierte Schutzmechanismen gegen solche Angriffe - diese müssen aber von Ihnen aktiviert werden, bevor sie genutzt werden können. Verwendet werden hierzu zwei globale Variablen im CGI-Namensraum:

    $CGI::POST_MAX
    Bei einem positiven Integerwert legt diese Variable eine Obergrenze (in Bytes) für die Größe eines POSTings fest. Erkennt CGI.pm eine POST-Operation, deren Größe über die Obergrenze hinausgeht, bricht das Modul unmittelbar mit einer Fehlermeldung ab. Dieser Wert betrifft sowohl normale POSTings als auch Multipart-POSTings, d.h., auch die maximale Größe von Datei-Uploads wird beschränkt. Sie sollten diese Variable auf einen vernünftig hohen Wert, etwa ein Megabyte, setzen.
    $CGI::DISABLE_UPLOADS
    Mit einem Wert ungleich null werden Datei-Uploads vollständig unterbunden. Die anderen Formularwerte funktionieren wie gehabt.

    Sie können diese Variablen auf zwei unterschiedliche Arten verwenden.

    1. Auf einer skriptorientierten Basis. Setzen Sie die Variable zu Beginn des Skripts, direkt nach der "use"-Anweisung:
    2. use CGI qw/:standard/;
      use CGI::Carp 'fataler Browser-Fehler';
      $CGI::POST_MAX=1024 * 100;  # maximal 100K POSTings
      $CGI::DISABLE_UPLOADS = 1;  # keine Uploads
    3. Global für alle Skripten. Schauen Sie sich CGI.pm an, finden Sie die Definitionen für $POST_MAX und $DISABLE_UPLOADS, und setzen Sie sie auf die gewünschten Werte. Sie finden sie am Anfang der Datei in einer Unterroutine namens initialize_globals().

    Weil der Versuch, ein POSTing mit mehr als $POST_MAX Bytes durchzuführen, zu einem fatalen Fehler führt, können Sie CGI::Carp verwenden, um den fatalen Fehler im Browser-Fenster auszugeben (siehe oben). Anderenfalls erhält der Benutzer nur die generische Fehlermeldung "Internal Server Error". Weitere Details finden Sie in der CGI-Manpage.

    Kompatibilität mit CGI-LIB.PL

    Um die Portierung von Programmen einfacher zu machen, die auf der cgi-lib.pl basieren, steht die Routine "ReadParse" zur Verfügung. Die Portierung ist einfach:

    ALTE VERSION
    require "cgi-lib.pl";
    &ReadParse;
    print "Der Wert der Antiquität liegt bei $in{antique}.\n";

    NEUE VERSION
    use CGI;
    CGI::ReadParse
    print "Der Wert der Antiquität liegt bei $in{antique}.\n";

    Die ReadParse()-Routine von CGI.pm erzeugt eine gebundene Variable namens %in, auf die Sie zugreifen können, um die Query-Variablen zu ermitteln. Wie bei ReadParse können Sie auch Ihre eigene Variable angeben. Selten verwendete Features von ReadParse, wie etwa die Erzeugung von @in- und $in-Variablen, werden nicht unterstützt.

    Sobald Sie ReadParse verwendet haben, gelangen Sie folgendermaßen an das Query-Objekt selbst:

    $q = $in{CGI};
    print $q->textfield(-name=>'wow',
                        -value=>'funktioniert das wirklich?');

    Auf diese Weise können Sie die interessanteren Merkmale von CGI.pm nutzen, ohne Ihre alten Skripten völlig neu schreiben zu müssen.


    VERSION

    Diese Manpage dokumentiert "CGI.pm" in der Version CGI.pm-2.43.


    Autor

    Copyright 1995-1997, Lincoln D. Stein. All rights reserved. It may be used and modified freely, but I do request that this copyright notice remain attached to the file. You may modify this module as you wish, but if you redistribute a modified version, please attach a note listing the modifications you have made.

    Bug-Reports und Kommentare richten Sie bitte an: lstein@genome.wi.mit.edu


    Übersetzer

    Deutsche Übersetzung von Peter Klicman,
    © 1998 by O'Reilly Verlag, Köln


    Danksagungen

    Vielen Dank an:

    Matt Heffron (heffron@falstaff.css.beckman.com)
    James Taylor (james.taylor@srs.gov)
    Scott Anguish <sanguish@digifix.com
    Mike Jewell (mlj3u@virginia.edu)
    Timothy Shimmin (tes@kbs.citri.edu.au)
    Joergen Haegg (jh@axis.se)
    Laurent Delfosse (delfosse@delfosse.com)
    Richard Resnick (applepi1@aol.com)
    Craig Bishop (csb@barwonwater.vic.gov.au)
    Tony Curtis (tc@vcpc.univie.ac.at)
    Tim Bunce (Tim.Bunce@ig.co.uk)
    Tom Christiansen (tchrist@convex.com)
    Andreas Koenig (k@franz.ww.TU-Berlin.DE)
    Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au)
    Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu)
    Stephen Dahmen (joyfire@inxpress.net)
    Ed Jordan (ed@fidalgo.net)
    David Alan Pisoni (david@cnation.com)
    Doug MacEachern (dougm@opengroup.org)
    Robin Houston (robin@oneworld.org)
    ...und viele, viele andere...
    für Vorschläge und Bug-Fixes.


    Ein vollständiges Beispiel für ein einfaches formularbasiertes Skript

    #!/usr/local/bin/perl
         
    use CGI;
     
    $query = new CGI;
    
    print $query->header;
    print $query->start_html("Beispiel eines CGI.pm-Formulars");
    print "<H1> Beispiel eines CGI.pm-Formulars</H1>\n";
    &print_prompt($query);
    &do_work($query);
    &print_tail;
    print $query->end_html;
     
    sub print_prompt {
       my($query) = @_;
     
       print $query->startform;
       print "<EM>Wie lautet Ihr Name?</EM><BR>";
       print $query->textfield('name');
       print $query->checkbox('Nicht mein wirklicher Name');
     
       print "<P><EM>Wo findet man englische Spatzen?</EM><BR>";
       print $query->checkbox_group(
                             -name=>'Sparrow locations',
                             -values=>[England,Frankreich,Spanien,Asien,Hoboken],
                             -linebreak=>'yes',
                             -defaults=>[England,Asien]);
     
       print "<P><EM>Wie weit können sie fliegen?</EM><BR>",
            $query->radio_group(
                    -name=>'how far',
                    -values=>['10 Meter','1 Kilometer','10 Kilometer','wirklich weit'],
                    -default=>'1 Kilometer');
     
       print "<P><EM>Ihre Lieblingsfarbe?</EM>  ";
       print $query->popup_menu(-name=>'Color',
                                -values=>['Schwarz','Braun','Rot','Gelb'],
                                -default=>'Rot');
     
       print $query->hidden('Reference','Monty Python und der Heilige Gral');
     
       print "<P><EM>Was haben Sie da?</EM><BR>";
       print $query->scrolling_list(
                     -name=>'possessions',
                     -values=>['Eine Kokosnuß','Einen Gral','Ein Icon',
                                  'Ein Schwert','Ein Ticket'],
                     -size=>5,
                     -multiple=>'true');
     
       print "<P><EM>Irgendwelche Kommentare?</EM><BR>";
       print $query->textarea(-name=>'Comments',
                                 -rows=>10,
                                 -columns=>50);
     
       print "<P>",$query->reset;
       print $query->submit('Action',Rufen');
       print $query->submit('Action','Schreien');
       print $query->endform;
       print "<HR>\n";
    }
     
    sub do_work {
       my($query) = @_;
       my(@values,$key);
    
       print "<H2>Hier die aktuellen Werte des Formulars</H2>";
    
       foreach $key ($query->param) {
          print "<STRONG>$key</STRONG> -> ";
          @values = $query->param($key);
          print join(", ",@values),"<BR>\n";
       }
    }
    
    sub print_tail {
       print <<END;
    <HR>
    <ADDRESS>Lincoln D. Stein</ADDRESS><BR>
    <A HREF="/">Homepage</A>
    END
    }


    Bugs

    Dieses Modul ist groß und monolithisch. Außerdem macht es viele Dinge, etwa die Verarbeitung von URLs, das Parsing von CGI-Eingaben, das Schreiben von HTML-Code etc., die auch von den LWP-Modulen erledigt werden. Eigentlich sollte es zugunsten der CGI::*-Module aufgegeben werden, aber irgendwie arbeite ich immer weiter daran.

    Beachten Sie, daß der Code wirklich verdreht ist, um Warnungen zu vermeiden, die bei der Ausführung mit dem -w-Switch auftreten könnten.


    Siehe auch

    CGI, URI, CGI, CGI, CGI, CGI, CGI, CGI, CGI, CGI