You are here: Perldoc Web>PerlDokumentListe>CGI (2005-06-11)
CGI Dokumentation | Download als POD | Wie kann ich hier etwas ändern?

Name

CGI - Simple Common Gateway Interface Class

Übersicht

  # CGI Skript, das ein Eingabeformular erzeugt
  # und die Eingabewerte zurückliefert

  use CGI qw/:standard/;
  print header,
        start_html('Ein einfaches Beispiel'),
        h1('Ein einfaches Beispiel'),
        start_form,
        "Wie heißen Sie? ",textfield('name'),p,
        "Die Kombination ist?", p,
        checkbox_group(-name=>'worte',
                       -values=>['ehne','mehne','muh'],
                       -defaults=>['ehne','mehne']), p,
        "Welche ist Ihre Lieblingsfarbe? ",
        popup_menu(-name=>'farbe',
                   -values=>['rot','grün','blau','grüngelb']),p,
        submit,
        end_form,
        hr;

   if (param()) {
       print "Sie heißen ",em(param('name')),p,
             "Die Schlüsselworte sind: ",em(join(", ",param('worte'))),p,
             "Ihre Lieblingsfarbe ist  ",em(param('farbe')),
             hr;
   }

Zusammenfassung

Diese Perl Klassen-Bibliothek stellt Perl5-Objekte bereit, um damit auf einfachen Weise Formulare zu erstellen und deren Inhalte zu untersuchen. Dieses Paket definiert CGI-Objekte, also Dinge, die die jeweilige Abfragezeichenkette und andere Zustandsvariable speichern. Indem man die Methoden des CGI-Objektes verwendet, können Sie die Schlüsselworte und Parameter untersuchen, die an Ihr Skript übergeben wurden, und solche Formulare erstellen, die ihre Anfangswerte aus der momentanen Anfragezeichenkette entnehmen (und damit Zustandsinformation über mehrere Aufrufe hinweg bewahren). Das Modul stellt Funktionen zur Verfügung, die Standard-HTML erzeugen, was Tipparbeit spart und Programmfehler vermindert. Es unterstützt ebenfalls fortgeschrittenere Möglichkeiten der CGI- Programmierung, wie Datei-Upload, Cookies, CSS, Server-Push und Frames.

Für diejenigen, die die Objektorientierung nicht benötigen, unterstützt CGI.pm ebenso auch einen einfachen funktionsorientierten Programmierstil.

Die aktuelle Version von CGI.pm ist verfügbar unter

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

Beschreibung

Programmierstile

CGI.pm unterstützt zwei Stilarten der Programmierung: objektorientierte Programmierung und funktionsorientierte Programmierung. Im objektorientierten Programmierstil erstellen Sie ein oder mehrere CGI-Objekte und benutzen dann deren Objektmethoden, um die verschiedenen Elemente der Seite zu erzeugen. Jedes CGI-Objekt startet mit der Liste der benannten Parameter, die an Ihr CGI-Skript vom Server übergeben wurden. Sie können die Objekte verändern, sie in eine Datei oder Datenbank speichern und sie wiederherstellen. Da diese Objekt den "Status" des CGI-Skriptes widerspiegeln, und weil die Parameterlisten der Objekte unabhängig von einander sind, ermöglicht das Ihnen den Zustand des Skriptes zu einem Zeitpunkt zu speichern und diesen später wieder herzustellen.

Im objektorientierten Programmierstil können Sie zum Beispiel auf die folgende Art eine einfache "Hallo Welt"-HTML-Seite erstellen:

   #!/usr/local/bin/perl -w
   use CGI;                             # CGI-Routinen laden
   $q = new CGI;                        # Neues CGI-Objekt erstellen
   print $q->header,                    # HTTP-Header erzeugen
         $q->start_html('Hallo Welt'),  # HTML starten
         $q->h1('Hallo Welt'),          # Überschrift der Ebene 1
         $q->end_html;                  # HTML beenden

Im funktionsorientierten Stil gibt es ein Standard-CGI-Objekt, mit dem Sie aber nur selten direkt zu tun haben. Statt dessen rufen Sie einfach Funktionen auf, um CGI-Parameter zu lesen, HTML-Tags zu erzeugen, Cookies zu verwalten und so weiter. Auf diese Art haben Sie zwar ein sauberere Programmierschnittstelle, sind aber im Gegenzug auf genau eine CGI-Objekt zu einer Zeit eingeschränkt. Das folgende Beispiel gibt dieselbe Seite aus, benutzt dafür aber die funktions- orientierte Schnittstelle. Der wesentliche Unterschied dabei ist, dass wir nun einen Satz von Funktionen (in der Regel die "Standard"-Funktionen) in unseren Namensraum importieren müssen, und dass wir kein CGI-Objekt erstellen müssen.

   #!/usr/local/bin/perl
   use CGI qw/:standard/;           # standard CGI-Routinen laden
   print header,                    # HTTP-Header erstellen
         start_html('Hallo Welt'),  # HTML starten
         h1('Hallo Welt'),          # Überschrift der Ebene 1
         end_html;                  # HTML beenden

Die Beispiele in diesem Dokument benutzen überwiegend den objektorientierten Stil. Im Abschnitt FUNKTIONEN IMPORTIEREN finden Sie wichtige Hinweise zur funktionsorientierten Programmierung in CGI.pm

Routinen von CGI.pm aufrufen

Die meisten CGI.pm-Routinen akzeptieren mehrere Aufrufparameter, manche kennen bis zu 20 optionale Argumente! Zur Vereinfachung kennen alle Routinen eine Übergabe mit benannten Parametern, was wie folgt aussieht:

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

Jedem Argument wird ein Minus-Zeichen vorangestellt. Weder die Reihenfolge noch die Groß-Kleinschreibung sind in der Argumentliste von Bedeutung. -type, -Type, oder auch -TYPE werden alle gleichermaßen akzeptiert. Tatsächlich muss nur das erste Argument mit einem Minus beginnen. Beginnt das erste Argument mit Minus, denkt sich CGI.pm diese auch für die folgenden Argumente, falls nötig.

Einige Routinen werden gewöhnlich mit nur einem Argument aufgerufen. In diesem Fall können Sie das eine Argument ohne Argumentname übergeben. header() ist eine solche Routine. Hier ist das Argument der Dokumententyp.

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

Bei welchen anderen Routinen dies genauso ist, ist weiter unten dokumentiert.

Manche benannten Argumente erwarten ein Skalar, manche eine Referenz auf ein Array, und manche eine Referenz auf einen Hash. Oft können Sie beliebige Argumenttypen benutzen und die Routine wird damit das tun, was am sinnvollsten ist. Zum Beispiel kann die Routine param() verwendet werden, um einen CGI- Parameter auf einen einzelnen Wert oder einen Multi-Wert zu setzen. Die zwei Fälle sehen dann so aus:

   $q->param(-name=>'gebaeck',-value=>'Berliner');
   $q->param(-name=>'gebaeck',-value=>['Berliner','Krapfen','Pfannkuchen']);

Viele Routinen in CGI.pm werden gar nicht explizit in dem Modul definiert, sondern bei Bedarf erzeugt. Dies gilt für die sogenannten HTML-Kürzel, jene Routinen, die HTML-Tags erzeugen, und die man zur Erzeugung von dynamisch erzeugten Seiten verwendet. HMTL-Tags haben sowohl Attribute (jene attribut="wert" Paare innerhalb des Tags) als auch Inhalt (der Teil zwischen öffnendem und schließendem Tag). Um zwischen diesen beiden zu unterscheiden verwendet CGI.pm die Konvention, die Attribute als Hash-Referenz im ersten Argument und den Inhalt - so vorhanden - in den weiteren Argumenten zu übergeben. Das sieht dann so aus:

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

HTML-Tags werden später noch detaillierter beschrieben.

Viele Leute, die zum ersten Mal mit CGI.pm arbeiten, sind irritiert von den unterschiedlichen Aufrufkonventionen für HTML-Kürzel einerseits, die geschweifte Klammern um die Attribute der HTML-Tags benötigen, im Unterschied zu anderen Routinen, die Attribute ohne diese Klammern erzeugen können. Lassen Sie sich nicht verwirren. Zu Ihrer Bequemlichkeit sind die geschweiften Klammern einfach nur optional in allen Routinen, außer den HTML-Kürzeln. Wenn Sie möchten, können Sie die geschweiften Klammern in allen Routinen verwenden, die benannte Parameter entgegennehmen. Zum Beispiel:

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

Wenn Sie den -w -Schalter verwenden, werden Sie gewarnt, dass einige Argumentnamen von CGI.pm in Konflikt zu Namen eingebauter Perl- Funktionen stehen. Am häufigsten sieht man dies für das Argument -values, das man bei der Erstellung von Auswahl-Menüs, Auswahlschalter-Gruppen und ähnlichem verwendet. Um diese Warnungen zu vermeiden, haben Sie mehrere Möglichkeiten:

  1. Wenn verfügbar, verwenden Sie für das Argument einen anderen Namen. Beispielsweise ist -value ein Alias für -values.

  2. Ändern Sie die Groß-Kleinschreibung, z. B. -Values

  3. Setzen Sie das Argument in Anführungszeichen, wie in '-values'

Viele Routinen werden mit einem Argument, das eigentlich nicht bekannt ist, etwas sinnvolles tun. Zum Beispiel können Sie Nicht-Standard HTTP-Header-Einträge erzeugen, indem Sie diese als benannte Argumente bereitstellen.

  print $q->header(-type  =>  'text/html',
                   -cost  =>  'Drei Fuffis',
                   -annoyance_level => 'hoch',
                   -complaints_to   => 'in die Tonne');

Dies wird den folgenden Nicht-Standard HTTP-Header produzieren:

   HTTP/1.0 200 OK
   Cost: Drei Fuffis
   Annoyance-level: hoch
   Complaints-to: in die Tonne
   Content-type: text/html

Bemerke, dass Unterstriche automatisch in Bindestriche umgesetzt werden. HTML-erzeugende Routinen machen eine andere Art der Umsetzung.

Diese Eigenschaft erlaubt es Ihnen, mit den sich schnell verändernden HTTP- und HTML-"Standards" Schritt zu halten.

Ein neues Abfrage-Objekt erzeugen (Objektorientierter Stil)

     $abfrage = new CGI;

Diese Anweisung wird die (über POST und GET) übergebene Eingabe zerlegen und sie in einem Perl5-Objekt namens $abfrage abspeichern.

Ein neues Abfrage-Objekt aus einer Eingabedatei erzeugen

     $abfrage = new CGI(EINGABEDATEI);

Wenn Sie der Methode new() ein Dateihandle übergeben, wird sie Parameter aus der Datei lesen (oder von STDIN, oder woherauchimmer). Die Datei kann in einem der Formate, wie sie weiter unten im Abschnitt über Fehlersuche beschrieben werden vorliegen (d. h. eine Folge von durch Zeilenschaltungen getrennte SCHLUESSEL=WERT Paare wird funktionieren). Bequemerweise wird diese Art Datei von der Methode save() erzeugt (siehe unten). Mehrere Datensätze können gespeichert und wieder eingelesen werden.

Perl-Puristen wird es erfreuen zu hören, dass diese Syntax auch Referenzen auf Dateihandle oder sogar Referenzen auf Dateihandle-Globs akzeptiert. Letzteres ist die "offizielle" Art Dateihandle zu übergeben:

    $abfrage = new CGI(\*STDIN);

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

Wenn Sie die funktionsorientierte Schnittstelle verwenden und Sie wollen den CGI-Status von einem Dateihandle initialisieren, dann tut man das mit restore_parameters() . Dies (re)initialisiert das Standard-CGI-Objekt aus dem angegebenen Dateihandle.

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

Die Referenz auf ein assoziatives Array ist ebenfalls geeignet, um das Abfrage-Objekt zu initialisieren:

    $abfrage = new CGI( {'Dinosaurier'=>'Barney',
                       'Lied'=>'Ich liebe dich',
                       'Freunde'=>[qw/Jessica George Nancy/]}
                    );

Oder mittels einer korrekt formatierten, URL-kodierten Abfrage- Zeichenkette:

    $abfrage = new CGI('Dinosaurier=Barney&Farbe=lila');

Oder von einem bereits existierenden CGI-Objekt (Gegenwärtig klont das die Parameterliste, aber nicht die Objekt-spezifischen Felder, wie etwa den autoescape-Status.):

    $alte_abfrage = new CGI;
    $neue_abfrage = new CGI($alte_abfrage);

Eine leere Abfrage erhält man durch Initialisierung mit einer Leerzeichenkette oder einem leeren Hash:

   $leer_abfrage = new CGI("");

       -oder-

   $leer_abfrage = new CGI({});

Eine Liste von Schlüsselworten aus der Abfrage auslesen

     @schluesselworte = $abfrage->keywords

Wenn das Skript als Folge einer <ISINDEX>-Suche aufgerufen wurde, können die eingelesenen Schlüsselworte als Array über die Methode keywords() abgerufen werden.

Die Namen aller an das Skript übergebenen Parameter auslesen

     @namen = $abfrage->param

Wenn das Skript mit einer Parameterliste aufgerufen wurde (z. B. "name1=wert1&name2=wert2&name3=wert3"), wird die Methode param() die Namen der Parameter als Liste zurückgeben. Wenn das Skript als <ISINDEX>-Skript mit einem Argument ohne kaufmännischem Und (&) aufgerufen wurde (z. B. "wert1+wert2+wert3"), gibt es einen Parameter "keywords", der die mit "+" zusammengefügten Schlüsselworte enthält.

Anmerkung: Seit Version 1.5 enthält das zurückgegebene Array der Parameternamen dieses in genau der Reihenfolge, wie sie vom Browser geliefert worden sind. Üblicherweise ist das die gleiche Reihenfolge, wie die Parameter im Formular definiert wurden. (Dies ist aber nicht Teil der Spezifikation, und deshalb auch nicht garantiert.)

Den Wert oder Werteliste eines einzelnen benannten Parameters lesen

    @werte = $abfrage->param('foo');

              -oder-

    $wert = $abfrage->param('foo');

Übergeben Sie an die Methode param() ein einzelnes Argument, um den Wert des benannten Parameters auszulesen. Wenn es ein Multi-Parameter ist (z. B. eine Mehrfachselektion in einer Mehrfach-Auswahlliste), können Sie die Rückgabe eines Arrays verlangen. Anderenfalls gibt die Methode einen einzelnen Wert zurück.

Wenn der Wert in der Abfrage-Zeichenkette nicht vorhanden ist, wie in "name1=&name2=" oder "name1&name2", wird er als Leerzeichenkette zurückgegeben. Dieses Verhalten ist neu in Version 2.63.

Wenn der Parameter überhaupt nicht existiert, gibt param() im skalaren Kontext undef und im Listenkontext eine leere Liste zurück.

Wert(e) eines benannten Parameters setzen

    $abfrage->param('foo','ein','Array','von','Werten');

Das setzt den Wert des benannten Parameters 'foo' auf ein Array von Werten. Dies ist eine Möglichkeit den Wert eines Feldes zu ändern NACHDEM das Skript zuvor bereits einmal aufgerufen worden war. (Eine andere stellt der Parameter -override dar, der von allen Methoden akzeptiert wird, die Formularelemente generieren.)

param() kennt außerdem auch den Aufruf mit benannten Parametern, was später noch genauer erläutert wird:

    $abfrage->param(-name=>'foo',-values=>['ein','Array','von','Werten']);

                              -oder-

    $abfrage->param(-name=>'foo',-value=>'der Wert');

Weitere Werte an einen benannten Parameter anhängen

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

Fügt einen Wert oder eine Liste von Werten dem benannten Parameter hinzu. Die Werte werden an das Ende angehängt, wenn der Parameter bereits existiert. Anderenfalls wird er Parameter angelegt. Bitte beachten, dass diese Methode nur die Argumentübergabe mittels benannter Parameter akzeptiert.

Alle Parameter in einen Namensraum importieren

   $anfrage->import_names('R');

Erzeugt eine Serie von Variablen im 'R'-Namensraum, etwa $R::foo, @R::foo. Für Schlüsselwertlisten wird eine Variable @R::keywords erscheinen. Wenn kein Namensraum benannt wird, wird die Methode 'Q' verwenden. WARNUNG: Importieren Sie nichts in 'main'; Das stellt ein hochgradiges Sicherheitsrisiko dar!!!!

Anmerkung 1: Variabelennamen werden bei Bedarf in gültige Perl- Variablennamen gewandelt. Alle ungültigen Zeichen werden durch Unterstriche ersetzt. Wenn die ursprünglichen Namen erhalten bleiben müssen, sollten Sie statt dessen die Methode param() verwenden, um auf die CGI-Variablen über ihren Namen zuzugreifen.

Anmerkung 2: In älteren Version hieß diese Methode import() . Seit Version 2.20 ist dieser Name getilgt, um Konflikte mit dem in Perl eingebauten Modul- import -Operator zu vermeiden.

Einen Parameter vollständig löschen

    $anfrage->delete('foo','bar','baz');

Löscht eine Liste von Parametern. Das ist manchmal nützlich um Parameter zurückzusetzen, die nicht beim erneuten Skriptaufruf weitergegeben werden sollen.

Wenn Sie die funktionsorientierte Schnittstelle verwenden, benutzen Sie statt dessen "Delete()", um Konflikte mit Perls eingebauten Operator delete zu vermeiden.

Alle Parameter löschen

   $anfrage->delete_all();

Leert das CGI-Objekt vollständig. Das mag nützlich sein um sicher zu stellen, dass alles auf Standardwerte zurückgesetzt ist, wenn Sie ein Eingabeformular erstellen.

Verwenden Sie statt dessen Delete_all(), wenn Sie die funktionsorientierte Schnittstelle verwenden.

Direkt auf die Parameterliste zugreifen

   $q->param_fetch('Adresse')->[1] = 'Spottdrosselweg 13';
   unshift @{$q->param_fetch(-name=>'Adresse')},'George Munster';

Wenn Sie auf die Parameterliste auf andere Art zugreifen müssen, als es durch die oben beschriebenen Methoden möglich ist, können Sie eine direkte Array-Referenz über die Methode param_fetch erhalten. Diese Array-Referenz auf die benannten Parameter, können Sie dann in jeder gewünschten Weise manipulieren.

Um den Aufruf im Stile benannter Argumente durchzuführen, benutzen Sie das -name Argument.

Die Parameterliste als Hash erhalten

    $params = $q->Vars;
    print $params->{'Adresse'};
    @foo = split("\0",$params->{'foo'});
    %params = $q->Vars;

    use CGI ':cgi-lib';
    $params = Vars;

Viele Leute möchten die gesamte Parameterliste als Hash geliefert bekommen, so dass die Namen der CGI-Parameter die Schlüssel und die Werte die Werte der CGI-Parameter sind. Die Methode Vars() leistet dies. Im skalaren Kontext gibt sie die Parameterliste als Referenz auf einen gebundenen (tied) Hash zurück. Die Änderung eines Eintrages im Hash, ändert den betreffenden Wert in der zu Grunde liegenden CGI-Parameterliste. Im Listenkontext liefert die Methode die Parameterliste als gewöhnlichen Hash zurück. In dem Fall können Sie die Parameterliste zwar lesen, aber nicht verändern.

Wenn Sie diese Methode verwenden, müssen Sie auf Multi-Werte in der CGI-Parameterliste Acht geben. Da ein Hash nicht zwischen skalarem und Listenkontext unterscheiden kann, werden Multi-Parameter als gepackte Zeichenkette mit dem Null-Zeichen "\0" als Trenner zurück geliefert. Um an die einzelnen Werte zu gelangen, müssen Sie die gepackte Zeichenkette zerlegen (split). Dies ist die von Steve Brenner vor langer Zeit in seinem Perl4-Modul cgi-lib.pl eingeführte Konvention.

Wenn Sie Vars() als Funktion aufrufen wollen, brauchen sie beim Import die :cgi-lib Funktionsmenge (Beachten Sie auch den Abschnitt über CGI-LIB-Kompatibilität).

Den Zustand des Skripts in einer Datei abspeichern

    $anfrage->save(DATEIHANDLE)

Dieser Aufruf speichert den momentanen Zustand des Formulars in dem angegebenen Dateihandle. Wenn Sie die Methode new() mit einem Dateihandle aufrufen, kann dies wieder eingelesen werden. Beachte: Das Dateihandle kann eine Datei, eine Pipe, wasauchimmer sein!

Das Format der gespeicherten Datei ist:

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

Sowohl Name, als auch Wert werden URL-kodiert. CGI-Multi-Parameter werden durch wiederholtes Nennen des Namens dargestellt. Ein Sitzungsdatensatz wird durch ein einzelnes Gleichheitszeichen (=) abgeschlossen. Sie können mehrere Datensätze herausschreiben und sie dann mittels mehrerer Aufrufen von new wieder einlesen. Wenn die Datei zum Anhängen geöffnet wird, kann dies über mehrere Sitzungen verteilt passieren. Damit können Sie ein primitives Gästebuch oder eine Historie von Anwenderanfragen realisieren. Hier ein kurzes Beispiel, wo mehrere Sitzungsdatensätze geschrieben werden:

   use CGI;

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

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

Das verwendete Dateiformat ist identisch zum Datenaustauschformat "Boulderio" des Whitehead Genome Centers und kann mit entsprechenden Boulderio-Hilfsprogrammen bearbeitet werden. Siehe

  http://stein.cshl.org/boulder/

für weitere Einzelheiten.

Wenn Sie diese Methode in der funktionsorientierten Schnittstelle (nicht-OO) verwenden wollen, ist der exportierte Methodenname save_parameters() .

CGI-Fehler verfolgen

Wenn Anwenderdaten verarbeitet werden, können Fehler auftreten, insbesondere beim Datei-Upload. Wenn solche Fehler auftreten, bricht CGI die Verarbeitung ab und liefert eine leere Parameterliste zurück. Die Funktion cgi_error() gibt Auskunft über Auftreten und Art der Fehler. Die Fehlermeldungen sind als HTTP Statuskode formatiert. Sie können den Fehlertext entweder in eine HTML-Seite einbauen, oder ihn direkt als HTTP-Status zurückgeben:

    my $fehler = $q->cgi_error;
    if ($fehler) {
        print $q->header(-status=>$fehler),
              $q->start_html('Probleme'),
              $q->h2('Anfrage nicht verarbeitet'),
              $q->strong($fehler);
        exit 0;
    }

Wenn Sie die funktionsorientierte Schnittstelle verwenden (siehe nächsten Abschnitt) können Fehler nur beim ersten Aufruf von param() auftreten. Seien Sie diesbezüglich gewappnet!

Die funktionsorientierte Schnittstelle verwenden

Um die funktionsorientierte Schnittstelle zu verwenden, müssen Sie angeben, welche Routinen bzw. Routinenmengen von CGI.pm in den Namensraum Ihres Skriptes importiert werden sollen. Mit diesem Import ist ein kleiner Mehraufwand verbunden, aber nicht viel.

   use CGI <Methodenliste>;

Die angegebenen Methoden werden in das aktuelle Packet (package) importiert. Sie können die Methoden dann sofort aufrufen, ohne erst ein CGI-Objekt zu erzeugen. Das folgende Beispiel zeigt, wie die Methoden param() und header() importiert werden und benutzt sie im Anschluss:

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

Öfter werden Sie ganze Gruppen von gebräuchlichen Funktionen importieren, indem Sie den entsprechenden Gruppennamen angeben. Alle Gruppennamen werden durch einen Doppelpunkt (:) eingeleitet, wie in :html3 (für die Tags, die im HTML3-Standard definiert sind).

Hier die Liste aller Funktionsgruppen, die Sie importieren können:

:cgi

Importiert alle CGI-Verwaltungsmethoden, wie param() , path_info() und so fort.

:form

Importiert alle Methoden zur Erzeugung von Eingabeformularen, wie beispielsweise textfield() .

:html2

Importiert alle Methoden, die HTML-2.0-Standardelemente erzeugen.

:html3

Importiert alle Methoden, die HTML-3.0-Standardelemente erzeugen (wie zum Beispiel <table>, <super> and <sub>).

:html4

Importiert alle Methoden, die HTML-4.0-Standardelemente erzeugen (wie zum Beispiel <abbrev>, <acronym> and <thead>).

:netscape

Importiert alle HTML-erzeugenden Methoden, für Netscape-spezifische HTML-Erweiterungen.

:html

Importiert alle HTML-erzeugenden Kürzel (d. h. 'html2' + 'html3' + 'netscape')...

:standard

Importiert die "Standard"-Merkmale, 'html2', 'html3', 'html4', 'form' und 'cgi'.

:all

Importiert alle verfügbaren Methoden. Für die vollständige Liste schauen Sie bitte in den Code von CGI.pm, wo die Variable %EXPORT_TAGS definiert wird.

Wenn Sie eine Funktion importieren, die nicht Teil von CGI.pm ist, wird das Modul sie als neuen HTML-Tag behandeln und die entsprechende Unterfunktion erstellen. Diesen können Sie dann wie jeden andere HTML-Tag verwenden. Auf diese Art, können wir mit dem sich schnell entwickelnden HMTL-"Standard" Schritt halten. Nehmen wir an, Microsoft führt ein neues Tag namens <gradient> ein (welches die Oberfläche des Anwenders mit Farbverläufen flutet, bis seine Maschine einen Reboot ausführt). Sie brauchen dann nicht auf eine neue Version von CGI.pm warten, um es sofort benutzen zu können:

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

Beachte: Im Interesse der Ausführungsgeschwindigkeit verwendet CGI.pm nicht die Standardsyntax des Exporter-Moduls, um die zu ladenden Symbole anzugeben. Dies könnte sich in der Zukunft ändern.

Wenn Sie irgendeine der zustandserhaltenden oder formulargenerierenden Methoden importieren, wird ein Standard-CGI-Objekt erstellt und automatisch bei der ersten Verwendung eingerichtet, wenn Sie eine der Methoden verwenden, die ein solches Objekt voraussetzen. Die trifft unter anderem auf param() , textfield() , submit() und ähnliche zu. (Wenn Sie direkten Zugriff auf dieses CGI-Objekt, brauchen finden Sie es in der globalen Variablen $CGI::Q .) Mit importierten Methoden von CGI.pm können Sie optisch elegante Skripte schreiben:

   use CGI qw/:standard/;
   print 
       header,
       start_html('Einfaches Skript'),
       h1('Einfaches Skript'),
       start_form,
       "Wie ist Ihr Name? ",textfield('name'),p,
       "Wie ist die Kombination?",
       checkbox_group(-name=>'worte',
                      -values=>['ehne','mehne','muh'],
                      -defaults=>['ehne','muh']),p,
       "Welche ist Ihre Lieblingsfarbe?",
       popup_menu(-name=>'farbe',
                  -values=>['rot','grün','blau','grüngelb']),p,
       submit,
       end_form,
       hr,"\n";

    if (param) {
       print 
           "Ihr Name ist ",em(param('name')),p,
           "Die Schlüsselworte sind: ",em(join(", ",param('worte'))),p,
           "Ihre Lieblingsfarbe ist ",em(param('farbe')),".\n";
    }
    print end_html;

Pragmas

Zusätzlich zu den Funktionsgruppen gibt es auch eine Reihe von Pragmas, die Sie importieren können. Pragmas werden immer durch ein Bindestrich eingeleitet und verändern die Funktionsweise von CGI.pm in vielfältiger Weise. Pragmas, Funktionsgruppen und einzelne Funktionsnamen können alle im selbem use() importiert werden. Beispielsweise importiert die folgende use-Anweisung die Standard-Funktionsgruppe und aktiviert den Debugging-Modus (Pragma -debug):

   use CGI qw/:standard -debug/;

Aktuell gibt es die folgenden Pragmas:

-any

Wenn Sie use CGI -any angeben, dann wird jede Methode, die das Anfrageobjekt nicht kennt, als neues HTML-Tag interpretiert. Dies erlaubt es Ihnen die nächsten ad hoc -HTML-Erweiterungen von Netscape oder Microsoft zu unterstützen. Hier können Sie sich mit neuen und nicht-unterstützten Tags austoben:

   use CGI qw(-any);
   $q=new CGI;
   print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});

Da die Verwendung von <cite>any</cite> bedeutet, dass jeder Tippfehler in einem Methodennamen als HTML-Tag interpretiert wird, benutzen Sie es mit Vorsicht oder überhaupt nicht.

-compile

Dies bewirkt, dass die angegebenen Methoden vorab kompiliert werden und dies nicht auf später vertagt wird. Für Skripte, die unter FastCGI oder mod_perl über einen längeren Zeitraum laufen oder die durch Malcolm Beatties Perl Compiler laufen sollen, ist dies sinnvoll. Verwenden Sie es zusammen mit den Methoden oder Methodenfamilien, die Sie verwenden werden.

   use CGI qw(-compile :standard :html3);

oder sogar

   use CGI qw(-compile :all);

Beachte: Die Verwendung des Pragmas -compile in dieser Art und Weise hat immer den Effekt, dass die kompilierten Funktionen in den aktuellen Namensraum importiert werden. Wenn Sie kompilieren wollen, ohne dass die Funktionen in Ihren Namensraum importiert werden sollen, dann verwenden Sie die Methode compile() statt dessen:

   use CGI();
   CGI->compile();

Das ist besonders nützlich in einer mod_perl-Umgebung, wo Sie ggf. alle CGI-Routinen in einem Startup-Skript vorkompilieren und dann individuell in jedes mod_perl-Skript importieren.

-nosticky

Dies bewirkt, dass CGI.pm die versteckten Felder .submit und .cgifields nicht erzeugt. Das ist sehr nützlich, wenn Sie diese versteckten Felder nicht in einer Anfrage mit GET auftauchen haben wollen. Ein Such-Skript beispielsweise, dass auf diese Weise erzeugt wird, hat eine schöne saubere URL mit Such-Parameters zum Bookmarken.

-no_undef_params

Dies hält CGI.pm davon ab, undef Parameter in die Parameterliste aufzunehmen.

-no_xhtml

Standardmäßig gibt CGI.pm ab Version 2.69 XHTML aus (http://www.w3.org/TR/xhtml1/). Das Pragma -no_xhtml schaltet dies ab. Dank geht an Michalis Kabrianis <kabrianis@hellug.gr> für diese Erweiterung.

-nph

Dies lässt CGI.pm einen Header ausgeben, der für eine NPH-Skript (no parsed header) geeignet ist. Sie müssen wahrscheinlich noch mehr tun, um dem Server mitzuteilen, dass das Skript NPH ist. NPH-Skripten werden weiter unten noch diskutiert.

-newstyle_urls

Trennt die name=wert Paare in CGI-Parameter-Abfrage-Zeichenketten mit Semikolons statt kaufmännischen Und-Zeichen voneinander. Zum Beispiel:

   ?name=fred;age=24;favorite_color=3

Mit Semikolon gebildete Abfrage-Zeichenketten werden immer akzeptiert, werden aber nicht von self_url() und query_string() ausgegeben, solange das Pragma -newstyle_url nicht angegeben wurde.

Dies wurde mit Version 2.64 der Standard.

-oldstyle_urls

Trennt die name=wert Paare in CGI-Parameter-Abfrage-Zeichenketten mit kaufmännischen Und-Zeichen statt Semikolons. Dies ist nicht mehr der Standard.

-autoload

Dies überschreibt den Autoloader, so dass jede nicht erkannte Funktion aus Ihrem Programm an CGI.pm verwiesen wird zur möglichen Auswertung. Das erlaubt ihnen alle Funktionen aus CGI.pm zu benutzen, ohne sie Ihrer Symboltabelle hinzufügen zu müssen, was für Anwender von mod_perl wichtig ist, die sich über Speicherverbrauch Sorgen machen. Warnung: Wenn -autoload aktiv ist, können Sie die Klammern bei den Funktionsaufrufe nicht weglassen ("poetry mode"). Benutzen Sie dann hr() anstatt hr , oder fügen Sie etwas wie use subs qw/hr p header/ am Anfang Ihres Skripts ein.

-no_debug

Dies schaltet die Möglichkeit der Kommandozeilen-Verarbeitung aus. Wenn Sie ein Programm mit CGI.pm auf der Kommandozeile laufen lassen wollen, um HTML zu erzeugen, aber keine CGI-Parameter über die Kommandozeileneingabe oder STDIN einlesen wollen, dann benutzen Sie dieses Pragma.

   use CGI qw(-no_debug :standard);

-debug

Dies aktiviert die vollen Debugging-Möglichkeiten. Zusätzlich zum Lesen von CGI-Argumenten aus der Kommandozeilen-Verarbeitung wird CGI.pm mit der Meldung "(offline mode: enter name=value pairs on standard input)" anhalten, um Argumente von STDIN einzulesen.

Konsultieren Sie den Abschnitt über Debugging für mehr Details zu diesem Thema.

-private_tempfiles

CGI.pm kann Datei-Uploads verarbeiten. Gewöhnlicherweise wird die heraufgeladene Datei in ein temporäres Verzeichnis gespeichert und wieder gelöscht, wenn die Bearbeitung abgeschlossen ist. Dies birgt allerdings die Gefahr abgehört zu werden, wie es im Abschnitt über Datei-Upload beschrieben wird. Ein anderer Autor eines CGI-Skriptes könnte sich die Daten während des Uploads anschauen, selbst wenn es sich um vertrauliche Informationen handelt. Auf Unix-Systemen bewirkt das Pragma -private_tempfiles, dass die temporäre Datei gelöscht wird, sobald sie geöffnet wird, noch bevor Daten hineingeschrieben werden. Das reduziert die Abhörgefahr, bannt sie aber nicht vollständig, da der Zugriff auf die Ressource nicht atomar ist (mögliche Race Condition). Um dem Angreifer das Leben schwerer zu machen, wählt das Programm den temporären Dateinamen, indem es eine 32-Bit-Checksumme des hereinkommenden HTTP-Headers bildet.

Um sicherzustellen, dass die temporäre Datei nicht von anderen CGI-Skripten gelesen werden kann, benutzen Sie suEXEC oder ein CGI-Wrapper-Programm um Ihr Skript laufen zu lassen. Die temporäre Datei wird mit Mode 0600 angelegt (weder von World noch von Group lesbar).

Das temporäre Verzeichnis wird nach folgenden Algorithmus bestimmt:

    1. Wenn der aktuelle Benutzer ein Verzeichnis
    "tmp" in seinem Home-Verzeichnis hat, benutze das (Nur
    Unix-Systeme).

    2. Wenn die Umgebungsvariable TMPDIR existiert, benutze den dort
    angegebenen Ort.

    3. Anderenfalls versuche die Orte /usr/tmp, /var/tmp, C:\temp,
    /tmp, /temp, ::Temporary Items, and \WWW_ROOT.

Jeder dieser Orte wird darauf geprüft, ob er ein Verzeichnis und beschreibbar ist. Wenn nicht, versucht der Algorithmus die nächste Wahl in der Liste.

Spezielle Arten HTML-Tag-Funktionen zu importieren

Viele der Methoden generieren HTML-Tags. Wie unten beschrieben wird, erzeugen Tag-Funktionen sowohl das öffnende als auch das schließende Tag. Zum Beispiel:

  print h1('Kopfzeile der Ebene 1');

erzeugt

  <h1>Kopfzeile der Ebene 1</h1>

Es wird Gelegenheiten geben, wo Sie das öffnende und das schließende Tag selbst erzeugen wollen. In dem Fall können Sie die Form start_ tag_name und end_ tag_name verwenden, wie in:

  print start_h1,'Kopfzeile der Ebene 1',end_h1;

Mit einigen (unten beschriebenen) Ausnahmen werden die Funktionen start_ tag_name und end_ tag_name nicht automatisch erzeugt, wenn Sie use CGI sagen. Sie können aber diejenigen Tags in der Import-Liste benennen für die Sie start/end -Tags erzeugt haben wollen, indem Sie entweder einen Stern (*) vor den Tagnamen setzen, oder alternative "start_ tag_name " bzw. "end_ tag_name " direkt anfordern.

Beispiel:

  use CGI qw/:standard *table start_ul/;

In diesem Beispiel werden zusätzlich zu den Standard-Funktionen, die folgenden Funktionen erzeugt:

1. start_table() (erzeugt das Tag <table>)

2. end_table() (erzeugt das Tag </table>)

3. start_ul() (erzeugt das Tag <ul>)

4. end_ul() (erzeugt das Tag </ul>)

Dynamische Dokumente erzeugen

Die meisten der Funktionen von CGI.pm beschäftigen sich damit Dokumente im Vorübergehen zu erzeugen. Im Allgemeinen werden Sie den HTTP-Header als erstes ausgeben, gefolgt vom eigentlichen Dokument. CGI.pm stellt Funktionen zur Verfügung, um verschiedene Typen von HTTP-Headern und HTML zu erstellen. Um GIF-Bilder zu erzeugen, schauen Sie sich bitte das Modul GD.pm an.

Jede dieser Funktionen gibt ein Fragment HTML oder HTTP zurück. Das können Sie direkt ausdrucken, so dass es im Browser-Fenster angezeigt wird. Sie können es aber auch an einen String anhängen, oder in eine Datei zur späteren Verwendung sichern.

Einen Standard-HTTP-Header erzeugen

Normalerweise wird das erste was Sie in einem CGI-Skript tun, das Ausdrucken eines HTTP-Headers sein. Das sagt dem Browser welche Art von Dokument er erwarten kann und übergibt weitere optionale Informationen, wie Sprache, Verfallszeitpunkt und ob das Dokument zwischengespeichert werden sollte. Der Header kann auch für spezielle Zwecke angepasst werden, zum Beispiel Server-Push oder kostenpflichtige Seiten.

        print $anfrage->header;

             -oder-

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

             -oder-

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

             -oder-

        print $anfrage->header(-type=>'image/gif',
                             -nph=>1,
                             -status=>'402 Payment required',
                             -expires=>'+3d',
                             -cookie=>$cookie,
                             -charset=>'utf-7',
                             -attachment=>'foo.gif',
                             -Cost=>'$2.00');

Der erste Parameter gibt den "Content-type:" vor. Sie können Ihren eigenen MIME-Typ wählen. Ansonsten ist der Standard text/html. Der optionale zweite Parameter gibt den Statuscode und eine Menschen-lesbare Meldung vor. Sie können hier zum Beispiel 204, "No response" angeben, um ein Skript zu erzeugen, dass den Browser anweist nichts zu tun.

Das letzte Beispiel zeigt die Argumentübergabe an die CGI-Methode mit benannten Parametern. Bekannte Parameter sind -type , -status , -expires , and -cookie . Allen anderen benannten Parameter werden, nachdem die einleitenden Bindestriche entfernt wurden, als Header-Felder ausgegeben. Das erlaubt Ihnen jeden von Ihnen benötigten Header zu spezifizieren. Innere Unterstriche werden in Bindestriche umgesetzt:

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

Die meisten Browser werden die Ausgabe von CGI-Skripten nicht in den Cachespeicher aufnehmen. Jedes Mal, wenn der Browser die Seite erneut lädt, wird das Skript wieder ausgeführt. Sie können dieses Verhalten mittels des Parameters -expires ändern. Wenn Sie mit diesem Parameter ein absolutes oder relatives Verfallsdatum angeben, werden einige Browser und Proxyserver die Skriptausgabe zwischenspeichern, bis das angegebene Verfallsdatum überschritten ist. Die folgenden sind alles gültige Angaben für das Feld -expires:

        +30s                              30 Sekunden ab jetzt
        +10m                              zehn Minuten ab jetzt
        +1h                               eine Stunde ab jetzt
        -1d                               gestern (d.h. "baldmöglichst")
        now                               sofort
        +3M                               in drei Monaten
        +10y                              in zehn Jahren
        Thursday, 25-Apr-1999 00:40:33 GMT  am angegebene Datum & Zeit

Der Parameter -cookie erzeugt einen Header, der den Browser anweist bei jeder folgenden Transaktion mit Ihrem Skript ein "Cookie" mitzugeben. Netscape-Cookies haben ein spezielles Format, das interessante Attribute, wie beispielsweise ein Verfallsdatum beinhaltet. Benutzen Sie die Methode cookie(), um Sitzungs-Cookies zu erzeugen und wiederzugewinnen.

Der Parameter -nph , wenn auf Wahr gesetzt, wird dafür sorgen, dass die korrekten Header für ein NPH-Skript (no parse header) ausgegeben werden. Es ist wichtig dies bei einigen Servern zu verwenden, die von allen Ihren Skripten erwarten NPH zu sein.

Der Parameter -charset kann verwendet werden, um den Zeichensatz anzugeben, der zum Browser geschickt wird. Falls nicht angegeben, ist ISO-8859-1 der Standard. Als Seiteneffekt wird auch die Methode charset() gesetzt.

Der Parameter -attachment kann benutzt werden, um die Seite in einen Anhang zu verwandeln. Anstatt die Seite anzuzeigen, fordern einige Browser dann dazu auf, die Seite auf die Festplatte zu speichern. Der Wert des Arguments ist der vorgeschlagene Name für die zu speichernde Datei. Damit das funktioniert, kann es sein, dass Sie den -type auf "application/octet-stream" setzen müssen.

Der Parameter -p3p fügt eine P3P-Kennung zum ausgegebenen Header hinzu. Der Parameter kann ein Array-Referenz oder eine Leerzeichen-unterteilter Zeichenkette von P3P-Kennungen sein. Zum Beispiel:

   print header(-p3p=>[qw(CAO DSP LAW CURa)]);
   print header(-p3p=>'CAO DSP LAW CURa');

In beiden Fällen wird das ausgegebene Header-Feld so formatiert:

  P3P: policyref="/w3c/p3p.xml" cp="CAO DSP LAW CURa"

Einen Umleitungs-Header erzeugen

   print $anfrage->redirect('http://somewhere.else/in/movie/land');

Manchmal wollen Sie ein Dokument nicht selbst erstellen, sondern den Browser nur anderswo hin umleiten. Vielleicht wählen Sie die URL basierend auf der Tageszeit oder der Identität des Benutzers.

Die Funktion redirect() leitet den Browser zu einer anderen URL um. Wenn Sie eine solche Umleitung verwenden, sollten nicht auch noch einen Header ausgeben.

Als Tipp von mir: Relative Links in Umleitungen zu anderen Dokumenten in der eigenen Site funktionieren möglicherweise nicht. Die liegt an einer wohl-beabsichtigten Optimierung, die von einigen Servern durchgeführt wird. Die Lösung in dem Fall ist es die vollständige URL, inklusive des http:-Teils, des Dokumentes zu dem Sie umleiteten wollen anzugeben.

Sie können auch benannte Argumente verwenden:

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

Der Parameter -nph , wenn auf Wahr gesetzt, wird dafür sorgen, dass die korrekten Header für ein NPH-Skript (no parse header) ausgegeben werden. Es ist wichtig dies bei einigen Servern zu verwenden, die von allen Ihren Skripten erwarten NPH zu sein, z. B. Microsofts IIS.

Den HTML-Dokumenten-Header erzeugen

   print $anfrage->start_html(-title=>'Geheimnis der Pyramiden',
                            -author=>'fred@capricorn.org',
                            -base=>'true',
                            -target=>'_blank',
                            -meta=>{'keywords'=>'pharao geheimnis mumie',
                                    'copyright'=>'copyright 1996 King Tut'},
                            -style=>{'src'=>'/styles/style1.css'},
                            -BGCOLOR=>'blue');

Nachdem der HTTP-Header erzeugt wurde, werde die meisten CGI-Skripten damit beginnen ein HTML-Dokument auszugeben. Die Routine start_html() erzeugt den Kopf der Seite, zusammen mit etlichen optionalen Informationen, die das Seitenaussehen und -verhalten bestimmen.

Diese Methode liefert einen kompletten HTML-Header und das öffnende <body>-Tag. Alle Parameter sind optional. In der Form mit benannten Parametern, werden die folgenden Parameter erkannt: -title, -author, -base, -xbase, -dtd, -lang und -target (siehe unten für Erklärungen zu diesen). Alle weiteren Parameter, die Sie mit übergeben, z. B. Netscapes BGCOLOR-Attribute, werden dem body-Tag hinzugefügt. Zusätzliche Parameter müssen mit einem Bindestrich eingeleitet werden.

Das Argument -xbase erlaubt Ihnen, ein HREF für das <base>-Tag anzugeben, das sich von der aktuellen Adresse unterscheidet, wie in

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

Alle relativen Links werden relativ zu diesem Tag interpretiert.

Das Argument -target erlaubt Ihnen ein Standard-Ziel-Frame für alle Links und Ausfüll-Formulare auf der Seite anzugeben. Dies ist kein Standard und funktioniert nur mit Netscape-Browsern! Konsultieren Sie die Netscape-Dokumentation zu Frames für Einzelheiten.

    -target=>"answer_window"

Alle relativen Links werden relativ zu diesem Tag interpretiert. Mit dem -meta -Argument fügen Sie dem Header beliebige Meta-Informationen hinzu. Das Argument erwartet eine Referenz auf ein assoziatives Array, das Name/Wert-Paare mit der Meta-Information enthält. Diese werden in eine Folge von <meta>-Header-Tags verwandelt, die dann etwa so aussehen:

    <meta name="keywords" content="pharao geheim mumie">
    <meta name="description" content="copyright 1996 King Tut">

Um einen <meta>-Tag vom Typ HTTP-EQUIV zu erzeugen, verwenden sie -head , wie weiter unten beschrieben.

Das Argument -style wird benutzt, um Cascading-Stylesheets in Ihren Code einzubinden. Für mehr Informationen hierzu schauen Sie bitte in den Abschnitt CASCADING-STYLESHEETS.

Das Argument -lang wird benutzt um ein Angabe zur Sprache in das <html>-Tag aufzunehmen. Der Standard, der gilt wenn nichts angegeben wird, ist "en-US" für US-Englisch. Beispiel:

    print $q->start_html(-lang=>'fr-CA');

Um das Sprach-Attribute zu unterdrücken, was Sie tun müssen, wenn Sie gültiges HTML 3.2 (oder früher) erzeugen wollen, übergeben Sie eine Leerzeichenkette (-lang=>'').

Das Argument -encoding kann benutzt werden, um den Zeichensatz für XHTML anzugeben. Der Standardwert ist iso-8859-1, wenn nicht angegeben.

Sie können dem <head>-Abschnitt beliebige weitere HTML-Elemente mit dem -head -Tag hinzufügen. Um beispielsweise das selten genutzte <link>-Element in den head-Abschnitt zu platzieren, benutzen Sie:

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

Um mehrere HTML-Elemente in den <head>-Abschnitt einzubinden, übergeben Sie einfach eine Array-Referenz:

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

Und hier sehen Sie, wie Sie einen HTTP-EQUIV-<meta>-Tag erzeugen:

      print start_html(-head=>meta({-http_equiv => 'Content-Type',
                                    -content    => 'text/html'}))

JAVASCRIPT: Die Parameter -script , -noScript , -onLoad , -onMouseOver , -onMouseOut und -onUnload werden benutzt, um JavaScript-Aufrufe zur Seite hinzuzufügen. -script sollte auf einen Abschnitt mit JavaScript-Funktions-Definitionen zeigen. Dieser Abschnitt wird als ein <script>-Abschnitt innerhalb des HTML-Headers (nicht HTTP) platziert. Der Abschnitt wird in den Header aufgenommen, damit Ihre Seite ein Chance hat die Funktionen vorzufinden, selbst wenn der Benutzer den Stopp-Knopf drückt, bevor die Seite vollständig geladen ist. CGI.pm versucht das Skript so zu formatieren, dass Browser, die nichts von JavaScript wissen, sich nicht daran verschlucken. Unglücklicherweise gibt es einige Browser, zum Beispiel Chimera unter Unix, die trotz allem verwirrt werden.

Die Parameter -onLoad und -onUnload zeigen auf JavaScript-Code-Fragmente, die ausgeführt werden sollen, wenn die Seite vom Browser geöffnet bzw. geschlossen wird. Üblicherweise werden hier Aufrufe von Funktionen angegeben, die im -script -Feld definiert wurden.

      $anfrage = new CGI;
      print $anfrage->header;
      $JSCRIPT=<<END;
      // Stell 'ne dumme Frage
      function raetselhaft() {
         var r = prompt("Was geht am Morgen auf vier, " +
                       "am Mittag auf zwei " +
                       "und am Abend auf drei Beinen?");
         beantworten(r);
      }
      // Bekomm 'ne dumme Antwort
      function beantworten(Antwort) {
         if (Antwort == "Mensch")
            alert("Richtig geraten!");
         else
            alert("Falsch!  Versuch's nochmal.");
      }
      END
      print $anfrage->start_html(-title=>'Das Rätsel der Sphinx',
                               -script=>$JSCRIPT);

Benutzen Sie den Parameter -noScript , um HTML-Text anzugeben, der angezeigt werden soll, in Browsern, die kein JavaScript können (oder wo JavaScript abgeschaltet ist).

Netscape 3.0 erkennt verschiedene Attribute des <script>-Tags, inklusive LANGUAGE und SRC. Das letztere ist besonders interessant, da es Ihnen erlaubt den JavaScript-Code in einer Datei oder einem CGI-Skript vorzuhalten, statt jede Seite mit dem Code vollzustopfen. Um diese Attribute zu verwenden, übergeben Sie eine Hash-Referenz im Parameter -script , mit einem oder mehreren der Attribute -language, -src oder -code als Schlüssel.

    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;"'}
               );

Schließlich gibt es eine Möglichkeit mehrere <script>-Abschnitte im Header zu erzeugen. Übergeben Sie dazu einfach die Liste der Abschnitte als eine Array-Referenz. Die ermöglicht es Ihnen unterschiedliche Quelldateien oder verschiedene JavaScript-Dialekte anzugeben. Beispiel:

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

Wenn das ein bisschen extrem aussieht, nehmen Sie meinen Rat an, und bleiben Sie bei gradlinigen CGI-Skripten.

Unter

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

finden Sie mehr Informationen zu JavaScript.

Nach altem Stil akzeptiert start_html() die folgenden Positionsparameter:

Parameter:

1.

Der Titel (<title>)

2.

E-Mail-Adresse des Autors (Erzeugt einen <link rev="MADE">-Tag, wenn vorhanden)

3.

Ein "Wahr"-Flag, wenn Sie ein <base>-Tag im Header aufnehmen wollen. So was hilft relative Adressen zu absoluten Adressen aufzulösen, wenn das Dokument verschoben wird. Allerdings macht es die Dokumenten-Hierarchie unportabel. Setzen Sie dies mit Vorsicht ein!

4, 5, 6...

Jeder weitere Parameter, den Sie in den <body>-Tag aufnehmen wollen. Das ist der richtige Ort, um Netscape-Erweiterungen, wie Farbangaben und Hintergrund-Muster anzugeben.

Das HTML-Dokument beenden

        print $anfrage->end_html

Das beendet das HTML-Dokument, indem es die Tags </body></html> ausgibt.

Mit einer selbstreferenzzierenden URL Zustandsinformation bewahren

    $myself = $anfrage->self_url;
    print q(<a href="$myself">Ich führe Selbstgespräche.</a>);

self_url() gibt eine URL zurück, die, wenn ausgewählt, das Skript wieder aufruft, mit all seinen Zustandsinformationen intakt. Das ist höchst nützlich, wenn Sie im Dokument mittels internen Ankern herumspringen wollen, aber die aktuellen Inhalte der Formularfelder nicht beeinträchtigen wollen. So was wie das folgende tut's:

     $myself = $anfrage->self_url;
     print "<a href=\"$myself#table1\">Vergleiche Tabelle 1</a>";
     print "<a href=\"$myself#table2\">Vergleiche Tabelle 2</a>";
     print "<a href=\"$myself#yourself\">Vergleichen Sie sich selbst</a>";

Wenn Sie mehr Kontrolle darüber wollen, was ausgegeben wird, benutzen Sie die Methode url() statt dessen.

Sie können sich auch die unverarbeitete Anfragezeichenkette mit query_string() geben lassen:

    $die_zeichenkette = $anfrage->query_string;

Die URL des Skripts erhalten

    $komplette_url = $anfrage->url();
    $komplette_url = $anfrage->url(-full=>1);  #alternative Syntax
    $relative_url  = $anfrage->url(-relative=>1);
    $absolute_url  = $anfrage->url(-absolute=>1);
    $url_mit_pfad  = $anfrage->url(-path_info=>1);
    $url_mit_pfad_und_anfrage = $anfrage->url(-path_info=>1,-query=>1);
    $netzort       = $anfrage->url(-base => 1);

url() gibt die URL des Skriptes in vielfältiger Form zurück. Ohne Argument aufgerufen, gibt es die komplette URL inklusive Hostnamen und Portnummer zurück.

    http://ihr.rechner.name/pfad/zum/skript.cgi

Durch die folgenden benannten Argumente, können Sie das Format verändern:

-absolute

Produziert eine absolute URL, wenn wahr, wie in

    /pfad/zum/skript.cgi

-relative

Produziert eine relative URL. Das ist nützlich, wenn Sie Ihr Skript mit veränderten Parametern wieder aufrufen wollen. Zum Beispiel:

    script.cgi

-full

Produziert die komplette URL, exakt so, wie ohne Argumente aufgerufen. Dies überschreibt die Argumente -relative und -absolute.

-path ( -path_info )

Hängt zusätzliche Pfadinformation an die URL an. Dies kann mit -full , -absolute oder -relative kombiniert werden. -path_info ist ein bereitgestelltes Synonym.

-query ( -query_string )

Hängt die Anfragezeichenkette an die URL an. Dies kann mit -full , -absolute oder -relative kombiniert werden. -query_string ist ein bereitgestelltes Synonym.

-base

Erzeugt nur das Protokoll und die Netz-Adresse, wie in http://www.foo.com:8000

POST- und URL-Parameter mischen

   $farbe = $anfrage->url_param('farbe');

Es ist für ein Skript möglich gleichzeitig CGI-Parameter über die URL und auch über Ausfüll-Formulare zu erhalten, indem ein Formular auf eine URL POSTet, die eine Abfragezeichenkette enthält (ein Fragezeichen "?", gefolgt von Argumenten). Die Methode param() wird immer den Inhalt des mit POST abgeschickten Formulars liefern und die Abfragezeichenkette der URL ignorieren. Um die Parameter aus der URL zu bekommen, rufen Sie die Methode url_param() auf. Verwenden Sie sie genauso, wie param() . Der Hauptunterschied ist, dass Sie so die Parameter zwar lesen, aber nicht setzen können.

Unter keinen Umständen wird der Inhalt der URL-Abfragezeichenkette gleichnamige gePOSTete Formularparameter beeinträchtigen. Wenn Sie versuchen eine URL-Abfragezeichenkette mit einem über GET aufgerufenen Formular zu mischen, wird das Ergebnis nicht so sein, wie Sie es erwarten.

Standard-HTML-Elemente erzeugen

CGI.pm definiert allgemeine HTML-Kürzel-Methoden für die meisten, wenn nicht alle Tags von HTML 3 und HTML 4. Die HTML-Kürzel sind nach einem einzelnen HTML-Element benannt, und geben ein Fragment HTML-Text zurück, das Sie dann ausdrucken oder anderweitig manipulieren können. Jedes Kürzel gibt ein Fragment HTML-Code zurück, den Sie an eine Zeichenkette anhängen, in eine Datei speichern, oder, was am normalsten ist, ausdrucken können, so dass es im Browserfenster angezeigt wird.

Dieses Beispiel zeigt, wie die HTML-Methoden benutzt werden:

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

Dies führt zu folgendem HTML-Code (zusätzliche Zeilenumbrüche wurden eingefügt, zwecks besserer Lesbarkeit):

   <blockquote>
   Vor vielen Jahren auf der Insel
   <a href="http://crete.org/">Kreta</a> da lebte
   ein Minotaur namens <strong>Fred.</strong> 
   </blockquote>
   <hr>

Wenn Sie diese Syntax zum Aufruf der HTML-Kürzel ungeschickt finden, können Sie sie auch in Ihren Namensraum importieren und sich nicht weiter mit der Objekt-Syntax abgeben (mehr dazu im nächsten Abschnitt):

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

Argumente an HTML-Kürzel übergeben

Die HTML-Methoden akzeptieren kein, ein oder viele Argumente. Wenn Sie kein Argument bereitstellen, erhalten Sie einen einzelnen Tag:

   print hr;          #  <hr>

Wenn Sie ein oder mehrere Zeichenketten-Argumente übergeben, werden diese mit Leerzeichen zusammengefügt und zwischen öffnendes und schließendes Tag platziert:

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

Wenn das erste Argument eine Referenz auf ein assoziatives Array ist, werden Schlüssel und Werte zu Attributen des HTML-Tag :

   print a({-href=>'fred.html',-target=>'_new'}, "Ein neues Fenster");

           <a href="fred.html",target="_new">Ein neues Fenster</a>

Wenn Sie wollen, können Sie auf die Bindestriche vor den Attributnamen verzichten:

   print img {src=>'fred.gif',align=>'LEFT'};

           <img align="LEFT" src="fred.gif">

Manchmal hat das Attribute eines HTML-Tags keinen Wert. Zum Beispiel können geordnete Listen als COMPACT markiert werden. Die Syntax für so ein Attribute ist ein Argument, das auf einen undefinierten Wert zeigt:

   print ol({compact=>undef},li('eins'),li('zwei'),li('drei'));

Vor Version 2.41 von CGI.pm, war es egal, ob sie eine Leerzeichenkette ('') oder undef als Attribut-Argument übergeben haben. Dies wurde allerdings geändert, um Tags der Form <img alt=""> erzeugen zu können. Der Unterschied wird anhand der folgenden Code-Stücke verdeutlicht:

   Code                   Ergebnis
   img({alt=>undef})      <img alt>
   img({alt=>''})         <img alt="">

Distributivität der HTML-Kürzel

Eine nette Eigenschaft der HTML-Kürzel ist ihre Distributivität. Wenn sie ihnen als Argument eine Referenz auf eine Liste übergeben, wird das Tag auf alle Elemente der Liste verteilt. Hier sehen Sie zum Beispiel eine Art eine geordnete Liste auszugeben:

   print ul(
             li({-type=>'disc'},['verschnupft','Doktor','schläfrig','glücklich'])
           );

Dieses Beispiel gibt folgendes HTML aus:

   <ul>
     <li type="disc">verschnupft</li>
     <li type="disc">Doktor</li>
     <li type="disc">schläfrig</li>
     <li type="disc">glücklich</li>
   </ul>

Das ist äußerst nützlich, um Tabellen zu erzeugen. Zum Beispiel:

   print table({-border=>undef},
           caption('Wann sollten Sie Ihr 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-Kürzel und Listen-Interpolation

Betrachten Sie das folgende Kodestück:

   print blockquote(em('Hallo'),'Mama!'));

Das wird normalerweise die Zeichenkette zurückgeben, die Sie erwarten, nämlich:

   <blockquote><em>Hallo</em> Mama!</blockquote>

Beachten Sie das Leerzeichen zwischen den Elementen "Hallo" und "Mama!". CGI.pm erzeugt dieses Leerzeichen bei der Listen-Interpolation, welche durch die magische Variable $" gesteuert wird. Manchmal werden Sie diese Leerzeichen dort nicht haben wollen, zum Beispiel wenn Sie eine Reihe Bilder ausrichten wollen. In dem Fall können Sie einfach den Wert von $" auf den Leerstring setzen.

    {
      local($") = '';
      print blockquote(em('Hallo'),'Mama!'));
    }

Ich schlage ver, dass Sie den Kode in einen Block, wie gezeigt, einschließen. Anderenfalls wirkt sich die Änderung auf $" auf den gesamten folgenden Kode aus, bis Sie sie ausdrücklich zurücknehmen.

Nicht-Standard HTML-Kürzel

Einige HTML-Tags folgen aus diversen Gründen nicht den Standardmustern.

comment() erzeugt einen HTML-Kommentar (<!-- Kommentar -->). Rufen Sie es so auf:

    print comment('hier steht mein Kommentar');

Wegen Konflikten mit eingebauten Perl-Funktionen, beginnen die folgenden Funktionen mit Großbuchstaben:

    Select
    Tr
    Link
    Delete
    Accept
    Sub

Des weiteren sind start_html(), end_html(), start_form(), end_form(), start_multipart_form() und alle Ausfüllformular-Tag-Funktionen speziell. Vergleichen Sie dazu deren jeweilige Abschnitte in diesem Dokument.

Automatische HTML-Zeichen-Sonderbehandlung (HTML-Escaping)

Standardmäßig wird jedes HTML, was von Formular-erzeugenden Funktionen ausgegeben wird, durch eine Funktion namens escapeHTML() geleitet:

$HTML_darstellung = escapeHTML("beliebige Zeichen");

Sonderzeichen zur HTML-Formatierung umwandeln.

Wenn Sie haben den (Standard-)Zeichensatz ISO-8859-1 spezifiziert haben, werden die Standard-Regeln zum Umsetzen der speziellen HTML-Zeichen angewendet. Das Zeichen "<" wird zu "<", ">" wird ">", "&" wird "&" und das Doppelanführungszeichen wird """. Weiterhin werden die hexadezimalen Zeichen 0x8b und 0x9b, welche manche Browser unkorrekter Weise als linke bzw. rechte spitze Klammer interpretieren, durch ihre entsprechende numerische Zeichen-Ersatzdarstellung ersetzt ("&#8249" and "›"). Wenn Sie den Zeichensatz umstellen, indem Sie entweder die Methode charset() aufrufen, oder indem Sie ein Argument -charset an header() übergeben, werden alle Zeichen in Form ihrer jeweiligen numerischen Zeichen-Ersatzdarstellung ausgegeben, da CGI.pm keine hinterlegte Tabelle aller möglichen Kodierungen hat.

Die automatische HMTL-Zeichenbehandlung findet nicht in anderen HTML-Kürzeln, wie z. B. h1() statt. Sie sollten selbst escapehHTML() für nicht vertrauenswürdige Daten aufrufen, um Ihre Seite vor den üblen Tricks zu schützen, die Leute bei Eingaben in Ihr Gästebuch, etc. versuchen könnten. Um den Zeichensatz umzustellen, benutzen Sie charset(). Sie können die HTML-Zeichen-Sonderbehandlung mit autoEscape(0) komplett abstellen.

$Zeichensatz = charset([$Zeichensatz]);

Ausgabe oder Setzen des aktuellen Zeichensatzes.

$flag = autoEscape([$flag]);

Ausgabe oder Setzen des autoEscape-Modus.

Formatierte HTML-Ausgabe (Pretty-Printing)

Standardmäßig enthalten die HTML-Zeichenketten, die von diesen Funktionen produziert werden, keine Zeilenumbrüche und Einrückungen. Igitt!, aber es reduziert die Größe des Dokuments um 10-20%. Um schön formatierte Ausgabe zu erhalten, benutzen Sie bitte CGI::Pretty?, eine abgeleitete Klasse, die von Brian Paulsen beigesteuert wurde.

CREATING FILL-OUT FORMS:

General note The various form-creating methods all return strings to the caller, containing the tag or tags that will create the requested form element. You are responsible for actually printing out these strings. It's set up this way so that you can place formatting tags around the form elements.

Another note The default values that you specify for the forms are only used the first time the script is invoked (when there is no query string). On subsequent invocations of the script (when there is a query string), the former values are used even if they are blank.

If you want to change the value of a field from its previous value, you have two choices:

(1) call the param() method to set it.

(2) use the -override (alias -force) parameter (a new feature in version 2.15). This forces the default value to be used, regardless of the previous value:

   print $anfrage->textfield(-name=>'field_name',
                           -default=>'starting value',
                           -override=>1,
                           -size=>50,
                           -maxlength=>80);

Yet another note By default, the text and labels of form elements are escaped according to HTML rules. This means that you can safely use "<CLICK ME>" as the label for a button. However, it also interferes with your ability to incorporate special HTML character sequences, such as Á, into your fields. If you wish to turn off automatic escaping, call the autoEscape() method with a false value immediately after creating the CGI object:

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

CREATING AN ISINDEX TAG

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

         -oder-

   print $anfrage->isindex($action);

Prints out an <isindex> tag. Not very exciting. The parameter -action specifies the URL of the script to process the query. The default is to process the query with the current script.

STARTING AND ENDING A FORM

    print $anfrage->start_form(-method=>$method,
                            -action=>$action,
                            -enctype=>$encoding);
      <... various form stuff ...>
    print $anfrage->endform;

        -oder-

    print $anfrage->start_form($method,$action,$encoding);
      <... various form stuff ...>
    print $anfrage->endform;

start_form() will return a <form> tag with the optional method, action and form encoding that you specify. The defaults are:

    method: POST
    action: this script
    enctype: application/x-www-form-urlencoded

endform() returns the closing </form> tag.

Start_form()'s enctype argument tells the browser how to package the various fields of the form before sending the form to the server. Two values are possible:

Note: This method was previously named startform(), and startform() is still recognized as an alias.

application/x-www-form-urlencoded

This is the older type of encoding used by all browsers prior to Netscape 2.0. It is compatible with many CGI scripts and is suitable for short fields containing text data. For your convenience, CGI.pm stores the name of this encoding type in &CGI::URL_ENCODED .

multipart/form-data

This is the newer type of encoding introduced by Netscape 2.0. It is suitable for forms that contain very large fields or that are intended for transferring binary data. Most importantly, it enables the "file upload" feature of Netscape 2.0 forms. For your convenience, CGI.pm stores the name of this encoding type in &CGI::MULTIPART

Forms that use this type of encoding are not easily interpreted by CGI scripts unless they use CGI.pm or another library designed to handle them.

For compatibility, the start_form() method uses the older form of encoding by default. If you want to use the newer form of encoding by default, you can call start_multipart_form() instead of start_form() .

JAVASCRIPTING: The -name and -onSubmit parameters are provided for use with JavaScript. The -name parameter gives the form a name so that it can be identified and manipulated by JavaScript functions. -onSubmit should point to a JavaScript function that will be executed just before the form is submitted to your server. You can use this opportunity to check the contents of the form for consistency and completeness. If you find something wrong, you can put up an alert box or maybe fix things up yourself. You can abort the submission by returning false from this function.

Usually the bulk of JavaScript functions are defined in a <script> block in the HTML header and -onSubmit points to one of these function call. See start_html() for details.

CREATING A TEXT FIELD

    print $anfrage->textfield(-name=>'field_name',
                            -default=>'starting value',
                            -size=>50,
                            -maxlength=>80);
        -oder-

    print $anfrage->textfield('field_name','starting value',50,80);

textfield() will return a text input field.

Parameters

1.

The first parameter is the required name for the field (-name).

2.

The optional second parameter is the default starting value for the field contents (-default).

3.
The optional third parameter is the size of the field in
      characters (-size).

4.
The optional fourth parameter is the maximum number of characters the
      field will accept (-maxlength).

As with all these methods, the field will be initialized with its previous contents from earlier invocations of the script. When the form is processed, the value of the text field can be retrieved with:

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

If you want to reset it from its initial value after the script has been called once, you can do so like this:

       $anfrage->param('foo',"I'm taking over this value!");

NEW AS OF VERSION 2.15: If you don't want the field to take on its previous value, you can force its current value by using the -override (alias -force) parameter:

    print $anfrage->textfield(-name=>'field_name',
                            -default=>'starting value',
                            -override=>1,
                            -size=>50,
                            -maxlength=>80);

JAVASCRIPTING: You can also provide -onChange , -onFocus , -onBlur , -onMouseOver , -onMouseOut and -onSelect parameters to register JavaScript event handlers. The onChange handler will be called whenever the user changes the contents of the text field. You can do text validation if you like. onFocus and onBlur are called respectively when the insertion point moves into and out of the text field. onSelect is called when the user changes the portion of the text that is selected.

CREATING A BIG TEXT FIELD

   print $anfrage->textarea(-name=>'foo',
                          -default=>'starting value',
                          -rows=>10,
                          -columns=>50);

        -oder-

   print $anfrage->textarea('foo','starting value',10,50);

textarea() is just like textfield, but it allows you to specify rows and columns for a multiline text entry box. You can provide a starting value for the field, which can be long and contain multiple lines.

JAVASCRIPTING: The -onChange , -onFocus , -onBlur , -onMouseOver , -onMouseOut , and -onSelect parameters are recognized. See textfield().

CREATING A PASSWORD FIELD

   print $anfrage->password_field(-name=>'secret',
                                -value=>'starting value',
                                -size=>50,
                                -maxlength=>80);
        -oder-

   print $anfrage->password_field('secret','starting value',50,80);

password_field() is identical to textfield(), except that its contents will be starred out on the web page.

JAVASCRIPTING: The -onChange , -onFocus , -onBlur , -onMouseOver , -onMouseOut and -onSelect parameters are recognized. See textfield().

CREATING A FILE UPLOAD FIELD

    print $anfrage->filefield(-name=>'uploaded_file',
                            -default=>'starting value',
                            -size=>50,
                            -maxlength=>80);
        -oder-

    print $anfrage->filefield('uploaded_file','starting value',50,80);

filefield() will return a file upload field for Netscape 2.0 browsers. In order to take full advantage of this you must use the new multipart encoding scheme for the form. You can do this either by calling start_form() with an encoding type of &CGI::MULTIPART , or by calling the new method start_multipart_form() instead of vanilla start_form() .

Parameters

1.

The first parameter is the required name for the field (-name).

2.

The optional second parameter is the starting value for the field contents to be used as the default file name (-default).

For security reasons, browsers don't pay any attention to this field, and so the starting value will always be blank. Worse, the field loses its "sticky" behavior and forgets its previous contents. The starting value field is called for in the HTML specification, however, and possibly some browser will eventually provide support for it.

3.

The optional third parameter is the size of the field in characters (-size).

4.

The optional fourth parameter is the maximum number of characters the field will accept (-maxlength).

When the form is processed, you can retrieve the entered filename by calling param():

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

Different browsers will return slightly different things for the name. Some browsers return the filename only. Others return the full path to the file, using the path conventions of the user's machine. Regardless, the name returned is always the name of the file on the user's machine, and is unrelated to the name of the temporary file that CGI.pm creates during upload spooling (see below).

The filename returned is also a file handle. You can read the contents of the file using standard Perl file reading calls:

        # Read a text file and print it out
        while (<$filename>) {
           print;
        }

        # Copy a binary file to somewhere safe
        open (OUTFILE,">>/usr/local/web/users/feedback");
        while ($bytesread=read($filename,$buffer,1024)) {
           print OUTFILE $buffer;
        }

However, there are problems with the dual nature of the upload fields. If you use strict , then Perl will complain when you try to use a string as a filehandle. You can get around this by placing the file reading code in a block containing the no strict pragma. More seriously, it is possible for the remote user to type garbage into the upload field, in which case what you get from param() is not a filehandle at all, but a string.

To be safe, use the upload() function (new in version 2.47). When called with the name of an upload field, upload() returns a filehandle, or undef if the parameter is not a valid filehandle.

     $fh = $anfrage->upload('uploaded_file');
     while (<$fh>) {
           print;
     }

In an array context, upload() will return an array of filehandles. This makes it possible to create forms that use the same name for multiple upload fields.

This is the recommended idiom.

When a file is uploaded the browser usually sends along some information along with it in the format of headers. The information usually includes the MIME content type. Future browsers may send other information as well (such as modification date and size). To retrieve this information, call uploadInfo(). It returns a reference to an associative array containing all the document headers.

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

If you are using a machine that recognizes "text" and "binary" data modes, be sure to understand when and how to use them (see the Camel book). Otherwise you may find that binary files are corrupted during file uploads.

There are occasionally problems involving parsing the uploaded file. This usually happens when the user presses "Stop" before the upload is finished. In this case, CGI.pm will return undef for the name of the uploaded file and set cgi_error() to the string "400 Bad request (malformed multipart POST)". This error message is designed so that you can incorporate it into a status code to be sent to the browser. Example:

   $file = $anfrage->upload('uploaded_file');
   if (!$file && $anfrage->cgi_error) {
      print $anfrage->header(-status=>$anfrage->cgi_error);
      exit 0;
   }

You are free to create a custom HTML page to complain about the error, if you wish.

If you are using CGI.pm on a Windows platform and find that binary files get slightly larger when uploaded but that text files remain the same, then you have forgotten to activate binary mode on the output filehandle. Be sure to call binmode() on any handle that you create to write the uploaded file to disk.

JAVASCRIPTING: The -onChange , -onFocus , -onBlur , -onMouseOver , -onMouseOut and -onSelect parameters are recognized. See textfield() for details.

CREATING A POPUP MENU

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

      -oder-

   %labels = ('eenie'=>'your first choice',
              'meenie'=>'your second choice',
              'minie'=>'your third choice');
   %attributes = ('eenie'=>{'class'=>'class of first choice'});
   print $anfrage->popup_menu('menu_name',
                            ['eenie','meenie','minie'],
          'meenie',\%labels,\%attributes);

        -or (named parameter style)-

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

popup_menu() creates a menu.

  1. The required first argument is the menu's name (-name).

  2. The required second argument (-values) is an array reference containing the list of menu items in the menu. You can pass the method an anonymous array, as shown in the example, or a reference to a named array, such as "\@foo".

  3. The optional third parameter (-default) is the name of the default menu choice. If not specified, the first item will be the default. The values of the previous choice will be maintained across queries.

  4. The optional fourth parameter (-labels) is provided for people who want to use different values for the user-visible label inside the popup menu and the value returned to your script. It's a pointer to an associative array relating menu values to user-visible labels. If you leave this parameter blank, the menu values will be displayed by default. (You can also leave a label undefined if you want to).

  5. The optional fifth parameter (-attributes) is provided to assign any of the common HTML attributes to an individual menu item. It's a pointer to an associative array relating menu values to another associative array with the attribute's name as the key and the attribute's value as the value.

When the form is processed, the selected value of the popup menu can be retrieved using:

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

JAVASCRIPTING: popup_menu() recognizes the following event handlers: -onChange , -onFocus , -onMouseOver , -onMouseOut , and -onBlur . See the textfield() section for details on when these handlers are called.

CREATING AN OPTION GROUP

Named parameter style

  print $anfrage->popup_menu(-name=>'menu_name',
                  -values=>[qw/eenie meenie minie/,
                            $q->optgroup(-name=>'optgroup_name',
                                         -values ['moe','catch'],
                                         -attributes=>{'catch'=>{'class'=>'red'}}),
                  -labels=>{'eenie'=>'one',
                            'meenie'=>'two',
                            'minie'=>'three'},
                  -default=>'meenie');

  Old style
  print $anfrage->popup_menu('menu_name',
                  ['eenie','meenie','minie',
                   $q->optgroup('optgroup_name', ['moe', 'catch'],
                         {'catch'=>{'class'=>'red'}})],'meenie',
                  {'eenie'=>'one','meenie'=>'two','minie'=>'three'});

optgroup creates an option group within a popup menu.

  1. The required first argument ( -name ) is the label attribute of the optgroup and is not inserted in the parameter list of the query.

  2. The required second argument ( -values ) is an array reference containing the list of menu items in the menu. You can pass the method an anonymous array, as shown in the example, or a reference to a named array, such as \@foo. If you pass a HASH reference, the keys will be used for the menu values, and the values will be used for the menu labels (see -labels below).

  3. The optional third parameter ( -labels ) allows you to pass a reference to an associative array containing user-visible labels for one or more of the menu items. You can use this when you want the user to see one menu string, but have the browser return your program a different one. If you don't specify this, the value string will be used instead ("eenie", "meenie" and "minie" in this example). This is equivalent to using a hash reference for the -values parameter.

  4. An optional fourth parameter ( -labeled ) can be set to a true value and indicates that the values should be used as the label attribute for each option element within the optgroup.

  5. An optional fifth parameter (-novals) can be set to a true value and indicates to suppress the val attribut in each option element within the optgroup.

    See the discussion on optgroup at W3C (http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTGROUP) for details.

  6. An optional sixth parameter (-attributes) is provided to assign any of the common HTML attributes to an individual menu item. It's a pointer to an associative array relating menu values to another associative array with the attribute's name as the key and the attribute's value as the value.

CREATING A SCROLLING LIST

   print $anfrage->scrolling_list('list_name',
                                ['eenie','meenie','minie','moe'],
        ['eenie','moe'],5,'true',{'moe'=>{'class'=>'red'}});
      -oder-

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

        -oder-

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

scrolling_list() creates a scrolling list.

Parameters:

1.

The first and second arguments are the list name (-name) and values (-values). As in the popup menu, the second argument should be an array reference.

2.

The optional third argument (-default) can be either a reference to a list containing the values to be selected by default, or can be a single value to select. If this argument is missing or undefined, then nothing is selected when the list first appears. In the named parameter version, you can use the synonym "-defaults" for this parameter.

3.

The optional fourth argument is the size of the list (-size).

4.

The optional fifth argument can be set to true to allow multiple simultaneous selections (-multiple). Otherwise only one selection will be allowed at a time.

5.

The optional sixth argument is a pointer to an associative array containing long user-visible labels for the list items (-labels). If not provided, the values will be displayed.

6.

The optional sixth parameter (-attributes) is provided to assign any of the common HTML attributes to an individual menu item. It's a pointer to an associative array relating menu values to another associative array with the attribute's name as the key and the attribute's value as the value.

When this form is processed, all selected list items will be returned as a list under the parameter name 'list_name'. The values of the selected items can be retrieved with:

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

JAVASCRIPTING: scrolling_list() recognizes the following event handlers: -onChange , -onFocus , -onMouseOver , -onMouseOut and -onBlur . See textfield() for the description of when these handlers are called.

CREATING A GROUP OF RELATED CHECKBOXES

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

   print $anfrage->checkbox_group('group_name',
                                ['eenie','meenie','minie','moe'],
        ['eenie','moe'],'true',\%labels,
        {'moe'=>{'class'=>'red'}});

   HTML3-COMPATIBLE BROWSERS ONLY:

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

checkbox_group() creates a list of checkboxes that are related by the same name.

Parameters:

1.

The first and second arguments are the checkbox name and values, respectively (-name and -values). As in the popup menu, the second argument should be an array reference. These values are used for the user-readable labels printed next to the checkboxes as well as for the values passed to your script in the query string.

2.

The optional third argument (-default) can be either a reference to a list containing the values to be checked by default, or can be a single value to checked. If this argument is missing or undefined, then nothing is selected when the list first appears.

3.

The optional fourth argument (-linebreak) can be set to true to place line breaks between the checkboxes so that they appear as a vertical list. Otherwise, they will be strung together on a horizontal line.

4.

The optional fifth argument is a pointer to an associative array relating the checkbox values to the user-visible labels that will be printed next to them (-labels). If not provided, the values will be used as the default.

5.

HTML3-compatible browsers (such as Netscape) can take advantage of the optional parameters -rows , and -columns . These parameters cause checkbox_group() to return an HTML3 compatible table containing the checkbox group formatted with the specified number of rows and columns. You can provide just the -columns parameter if you wish; checkbox_group will calculate the correct number of rows for you.

6.

The optional sixth parameter (-attributes) is provided to assign any of the common HTML attributes to an individual menu item. It's a pointer to an associative array relating menu values to another associative array with the attribute's name as the key and the attribute's value as the value.

To include row and column headings in the returned table, you can use the -rowheaders and -colheaders parameters. Both of these accept a pointer to an array of headings to use. The headings are just decorative. They don't reorganize the interpretation of the checkboxes -- they're still a single named unit.

When the form is processed, all checked boxes will be returned as a list under the parameter name 'group_name'. The values of the "on" checkboxes can be retrieved with:

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

The value returned by checkbox_group() is actually an array of button elements. You can capture them and use them within tables, lists, or in other creative ways:

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

JAVASCRIPTING: checkbox_group() recognizes the -onClick parameter. This specifies a JavaScript code fragment or function call to be executed every time the user clicks on any of the buttons in the group. You can retrieve the identity of the particular button clicked on using the "this" variable.

CREATING A STANDALONE CHECKBOX

    print $anfrage->checkbox(-name=>'checkbox_name',
                           -checked=>1,
                           -value=>'ON',
                           -label=>'CLICK ME');

        -oder-

    print $anfrage->checkbox('checkbox_name','checked','ON','CLICK ME');

checkbox() is used to create an isolated checkbox that isn't logically related to any others.

Parameters:

1.

The first parameter is the required name for the checkbox (-name). It will also be used for the user-readable label printed next to the checkbox.

2.

The optional second parameter (-checked) specifies that the checkbox is turned on by default. Synonyms are -selected and -on.

3.

The optional third parameter (-value) specifies the value of the checkbox when it is checked. If not provided, the word "on" is assumed.

4.

The optional fourth parameter (-label) is the user-readable label to be attached to the checkbox. If not provided, the checkbox name is used.

The value of the checkbox can be retrieved using:

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

JAVASCRIPTING: checkbox() recognizes the -onClick parameter. See checkbox_group() for further details.

CREATING A RADIO BUTTON GROUP

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

        -oder-

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

   HTML3-COMPATIBLE BROWSERS ONLY:

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

radio_group() creates a set of logically-related radio buttons (turning one member of the group on turns the others off)

Parameters:

1.

The first argument is the name of the group and is required (-name).

2.

The second argument (-values) is the list of values for the radio buttons. The values and the labels that appear on the page are identical. Pass an array reference in the second argument, either using an anonymous array, as shown, or by referencing a named array as in "\@foo".

3.

The optional third parameter (-default) is the name of the default button to turn on. If not specified, the first item will be the default. You can provide a nonexistent button name, such as "-" to start up with no buttons selected.

4.

The optional fourth parameter (-linebreak) can be set to 'true' to put line breaks between the buttons, creating a vertical list.

5.

The optional fifth parameter (-labels) is a pointer to an associative array relating the radio button values to user-visible labels to be used in the display. If not provided, the values themselves are displayed.

6.

HTML3-compatible browsers (such as Netscape) can take advantage of the optional parameters -rows , and -columns . These parameters cause radio_group() to return an HTML3 compatible table containing the radio group formatted with the specified number of rows and columns. You can provide just the -columns parameter if you wish; radio_group will calculate the correct number of rows for you.

6.

The optional sixth parameter (-attributes) is provided to assign any of the common HTML attributes to an individual menu item. It's a pointer to an associative array relating menu values to another associative array with the attribute's name as the key and the attribute's value as the value.

To include row and column headings in the returned table, you can use the -rowheader and -colheader parameters. Both of these accept a pointer to an array of headings to use. The headings are just decorative. They don't reorganize the interpretation of the radio buttons -- they're still a single named unit.

When the form is processed, the selected radio button can be retrieved using:

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

The value returned by radio_group() is actually an array of button elements. You can capture them and use them within tables, lists, or in other creative ways:

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

CREATING A SUBMIT BUTTON

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

        -oder-

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

submit() will create the query submission button. Every form should have one of these.

Parameters:

1.

The first argument (-name) is optional. You can give the button a name if you have several submission buttons in your form and you want to distinguish between them. The name will also be used as the user-visible label. Be aware that a few older browsers don't deal with this correctly and never send back a value from a button.

2.

The second argument (-value) is also optional. This gives the button a value that will be passed to your script in the query string.

You can figure out which button was pressed by using different values for each one:

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

JAVASCRIPTING: radio_group() recognizes the -onClick parameter. See checkbox_group() for further details.

CREATING A RESET BUTTON

   print $anfrage->reset

reset() creates the "reset" button. Note that it restores the form to its value from the last time the script was called, NOT necessarily to the defaults.

Note that this conflicts with the Perl reset() built-in. Use CORE::reset() to get the original reset function.

CREATING A DEFAULT BUTTON

   print $anfrage->defaults('button_label')

defaults() creates a button that, when invoked, will cause the form to be completely reset to its defaults, wiping out all the changes the user ever made.

CREATING A HIDDEN FIELD

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

                -oder-

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

hidden() produces a text field that can't be seen by the user. It is useful for passing state variable information from one invocation of the script to the next.

Parameters:

1.

The first argument is required and specifies the name of this field (-name).

2.

The second argument is also required and specifies its value (-default). In the named parameter style of calling, you can provide a single value here or a reference to a whole list

Fetch the value of a hidden field this way:

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

Note, that just like all the other form elements, the value of a hidden field is "sticky". If you want to replace a hidden field with some other values after the script has been called once you'll have to do it manually:

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

CREATING A CLICKABLE IMAGE BUTTON

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

        -oder-

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

image_button() produces a clickable image. When it's clicked on the position of the click is returned to your script as "button_name.x" and "button_name.y", where "button_name" is the name you've assigned to it.

JAVASCRIPTING: image_button() recognizes the -onClick parameter. See checkbox_group() for further details.

Parameters:

1.

The first argument (-name) is required and specifies the name of this field.

2.

The second argument (-src) is also required and specifies the URL

3. The third option (-align, optional) is an alignment type, and may be TOP, BOTTOM or MIDDLE
Fetch the value of the button this way:
     $x = $anfrage->param('button_name.x');
     $y = $anfrage->param('button_name.y');

CREATING A JAVASCRIPT ACTION BUTTON

     print $anfrage->button(-name=>'button_name',
                          -value=>'user visible label',
                          -onClick=>"do_something()");

        -oder-

     print $anfrage->button('button_name',"do_something()");

button() produces a button that is compatible with Netscape 2.0's JavaScript. When it's pressed the fragment of JavaScript code pointed to by the -onClick parameter will be executed. On non-Netscape browsers this form element will probably not even display.

HTTP COOKIES

Netscape browsers versions 1.1 and higher, and all versions of Internet Explorer, support a so-called "cookie" designed to help maintain state within a browser session. CGI.pm has several methods that support cookies.

A cookie is a name=value pair much like the named parameters in a CGI query string. CGI scripts create one or more cookies and send them to the browser in the HTTP header. The browser maintains a list of cookies that belong to a particular Web server, and returns them to the CGI script during subsequent interactions.

In addition to the required name=value pair, each cookie has several optional attributes:

1. an expiration time

This is a time/date string (in a special GMT format) that indicates when a cookie expires. The cookie will be saved and returned to your script until this expiration date is reached if the user exits the browser and restarts it. If an expiration date isn't specified, the cookie will remain active until the user quits the browser.

2. a domain

This is a partial or complete domain name for which the cookie is valid. The browser will return the cookie to any host that matches the partial domain name. For example, if you specify a domain name of ".capricorn.com", then the browser will return the cookie to Web servers running on any of the machines "www.capricorn.com", "www2.capricorn.com", "feckless.capricorn.com", etc. Domain names must contain at least two periods to prevent attempts to match on top level domains like ".edu". If no domain is specified, then the browser will only return the cookie to servers on the host the cookie originated from.

3. a path

If you provide a cookie path attribute, the browser will check it against your script's URL before returning the cookie. For example, if you specify the path "/cgi-bin", then the cookie will be returned to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", and "/cgi-bin/customer_service/complain.pl", but not to the script "/cgi-private/site_admin.pl". By default, path is set to "/", which causes the cookie to be sent to any CGI script on your site.

4. a "secure" flag

If the "secure" attribute is set, the cookie will only be sent to your script if the CGI request is occurring on a secure channel, such as SSL.

The interface to HTTP cookies is the cookie() method:

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

cookie() creates a new cookie. Its parameters include:

-name

The name of the cookie (required). This can be any string at all. Although browsers limit their cookie names to non-whitespace alphanumeric characters, CGI.pm removes this restriction by escaping and unescaping cookies behind the scenes.

-value

The value of the cookie. This can be any scalar value, array reference, or even associative array reference. For example, you can store an entire associative array into a cookie this way:

        $cookie=$anfrage->cookie(-name=>'family information',
                               -value=>\%childrens_ages);

-path

The optional partial path for which this cookie will be valid, as described above.

-domain

The optional partial domain for which this cookie will be valid, as described above.

-expires

The optional expiration date for this cookie. The format is as described in the section on the header() method:

        "+1h"  one hour from now

-secure

If set to true, this cookie will only be used within a secure SSL session.

The cookie created by cookie() must be incorporated into the HTTP header within the string returned by the header() method:

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

To create multiple cookies, give header() an array reference:

        $cookie1 = $anfrage->cookie(-name=>'riddle_name',
                                  -value=>"The Sphynx's Question");
        $cookie2 = $anfrage->cookie(-name=>'answers',
                                  -value=>\%answers);
        print $anfrage->header(-cookie=>[$cookie1,$cookie2]);

To retrieve a cookie, request it by name by calling cookie() method without the -value parameter:

        use CGI;
        $anfrage = new CGI;
        $riddle = $anfrage->cookie('riddle_name');
        %answers = $anfrage->cookie('answers');

Cookies created with a single scalar value, such as the "riddle_name" cookie, will be returned in that form. Cookies with array and hash values can also be retrieved.

The cookie and CGI namespaces are separate. If you have a parameter named 'answers' and a cookie named 'answers', the values retrieved by param() and cookie() are independent of each other. However, it's simple to turn a CGI parameter into a cookie, and vice-versa:

   # turn a CGI parameter into a cookie
   $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
   # vice-versa
   $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);

See the cookie.cgi example script for some ideas on how to use cookies effectively.

WORKING WITH FRAMES

It's possible for CGI.pm scripts to write into several browser panels and windows using the HTML 4 frame mechanism. There are three techniques for defining new frames programmatically:

1. Create a <Frameset> document

After writing out the HTTP header, instead of creating a standard HTML document using the start_html() call, create a <frameset> document that defines the frames on the page. Specify your script(s) (with appropriate parameters) as the SRC for each of the frames.

There is no specific support for creating <frameset> sections in CGI.pm, but the HTML is very simple to write. See the frame documentation in Netscape's home pages for details

  http://home.netscape.com/assist/net_sites/frames.html

2. Specify the destination for the document in the HTTP header

You may provide a -target parameter to the header() method:

    print $q->header(-target=>'ResultsWindow');

This will tell the browser to load the output of your script into the frame named "ResultsWindow". If a frame of that name doesn't already exist, the browser will pop up a new window and load your script's document into that. There are a number of magic names that you can use for targets. See the frame documents on Netscape's home pages for details.

3. Specify the destination for the document in the <form> tag

You can specify the frame to load in the FORM tag itself. With CGI.pm it looks like this:

    print $q->start_form(-target=>'ResultsWindow');

When your script is reinvoked by the form, its output will be loaded into the frame named "ResultsWindow". If one doesn't already exist a new window will be created.

The script "frameset.cgi" in the examples directory shows one way to create pages in which the fill-out form and the response live in side-by-side frames.

LIMITED SUPPORT FOR CASCADING STYLE SHEETS

CGI.pm has limited support for HTML3's cascading style sheets (css). To incorporate a stylesheet into your document, pass the start_html() method a -style parameter. The value of this parameter may be a scalar, in which case it is incorporated directly into a <style> section, or it may be a hash reference. In the latter case you should provide the hash with one or more of -src or -code . -src points to a URL where an externally-defined stylesheet can be found. -code points to a scalar value to be incorporated into a <style> section. Style definitions in -code override similarly-named ones in -src , hence the name "cascading."

You may also specify the type of the stylesheet by adding the optional -type parameter to the hash pointed to by -style . If not specified, the style defaults to 'text/css'.

To refer to a style within the body of your document, add the -class parameter to any HTML element:

    print h1({-class=>'Fancy'},'Welcome to the Party');

Or define styles on the fly with the -style parameter:

    print h1({-style=>'Color: red;'},'Welcome to Hell');

You may also use the new span() element to apply a style to a section of text:

    print span({-style=>'Color: red;'},
               h1('Welcome to Hell'),
               "Where did that handbasket get to?"
               );

Note that you must import the ":html3" definitions to have the span() method available. Here's a quick and dirty example of using CSS's. See the CSS specification at http://www.w3.org/pub/WWW/TR/Wd-css-1.html for more information.

    use CGI qw/:standard :html3/;

    #here's a stylesheet incorporated directly into the page
    $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 with Style',
                      -style=>{-src=>'http://www.capricorn.com/style/st1.css',
                               -code=>$newStyle}
                     );
    print h1('CGI with Style'),
          p({-class=>'Tip'},
            "Better read the cascading style sheet spec before playing with this!"),
          span({-style=>'color: magenta'},
               "Look Mom, no hands!",
               p(),
               "Whooo wee!"
               );
    print end_html;

Pass an array reference to -style in order to incorporate multiple stylesheets into your document.

Should you wish to incorporate a verbatim stylesheet that includes arbitrary formatting in the header, you may pass a -verbatim tag to the -style hash, as follows:

print $q->start_html (-STYLE  =>  {-verbatim => '@import
url("/server-common/css/'.$cssFile.'");',
                      -src      =>  '/server-common/css/core.css'});
</blockquote></pre>

This will generate an HTML header that contains this:

 <link rel="stylesheet" type="text/css"  href="/server-common/css/core.css">
   <style type="text/css">
   @import url("/server-common/css/main.css");
   </style>

Any additional arguments passed in the -style value will be incorporated into the <link> tag. For example:

 start_html(-style=>{-src=>['/styles/print.css','/styles/layout.css'],
                          -media => 'all'});

This will give:

 <link rel="stylesheet" type="text/css" href="/styles/print.css" media="all"/>
 <link rel="stylesheet" type="text/css" href="/styles/layout.css" media="all"/>

<p>

To make more complicated <link> tags, use the Link() function and pass it to start_html() in the -head argument, as in:

  @h = (Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/ss.css',-media=>'all'}),
        Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/fred.css',-media=>'paper'}));
  print start_html({-head=>\@h})

DEBUGGING

If you are running the script from the command line or in the perl debugger, you can pass the script a list of keywords or parameter=value pairs on the command line or from standard input (you don't have to worry about tricking your script into reading from environment variables). You can pass keywords like this:

    your_script.pl keyword1 keyword2 keyword3

or this:

   your_script.pl keyword1+keyword2+keyword3

or this:

    your_script.pl name1=value1 name2=value2

or this:

    your_script.pl name1=value1&name2=value2

To turn off this feature, use the -no_debug pragma.

To test the POST method, you may enable full debugging with the -debug pragma. This will allow you to feed newline-delimited name=value pairs to the script on standard input.

When debugging, you can use quotes and backslashes to escape characters in the familiar shell manner, letting you place spaces and other funny characters in your parameter=value pairs:

   your_script.pl "name1='I am a long value'" "name2=two\ words"

DUMPING OUT ALL THE NAME/VALUE PAIRS

The Dump() method produces a string consisting of all the query's name/value pairs formatted nicely as a nested list. This is useful for debugging purposes:

    print $anfrage->Dump

Produces something that looks like:

    <ul>
    <li>name1
        <ul>
        <li>value1
        <li>value2
        </ul>
    <li>name2
        <ul>
        <li>value1
        </ul>
    </ul>

As a shortcut, you can interpolate the entire CGI object into a string and it will be replaced with the a nice HTML dump shown above:

    $anfrage=new CGI;
    print "<h2>Current Values</h2> $anfrage\n";

FETCHING ENVIRONMENT VARIABLES

Some of the more useful environment variables can be fetched through this interface. The methods are as follows:

Accept()

Return a list of MIME types that the remote browser accepts. If you give this method a single argument corresponding to a MIME type, as in $anfrage->Accept('text/html'), it will return a floating point value corresponding to the browser's preference for this type from 0.0 (don't want) to 1.0. Glob types (e.g. text/*) in the browser's accept list are handled correctly.

Note that the capitalization changed between version 2.43 and 2.44 in order to avoid conflict with Perl's accept() function.

raw_cookie()

Returns the HTTP_COOKIE variable, an HTTP extension implemented by Netscape browsers version 1.1 and higher, and all versions of Internet Explorer. Cookies have a special format, and this method call just returns the raw form (?cookie dough). See cookie() for ways of setting and retrieving cooked cookies.

Called with no parameters, raw_cookie() returns the packed cookie structure. You can separate it into individual cookies by splitting on the character sequence "; ". Called with the name of a cookie, retrieves the unescaped form of the cookie. You can use the regular cookie() method to get the names, or use the raw_fetch() method from the CGI::Cookie module.

user_agent()

Returns the HTTP_USER_AGENT variable. If you give this method a single argument, it will attempt to pattern match on it, allowing you to do something like $anfrage->user_agent(netscape);

path_info()

Returns additional path information from the script URL. E.G. fetching /cgi-bin/your_script/additional/stuff will result in $anfrage->path_info() returning "/additional/stuff".

NOTE: The Microsoft Internet Information Server is broken with respect to additional path information. If you use the Perl DLL library, the IIS server will attempt to execute the additional path information as a Perl script. If you use the ordinary file associations mapping, the path information will be present in the environment, but incorrect. The best thing to do is to avoid using additional path information in CGI scripts destined for use with IIS.

path_translated()

As per path_info() but returns the additional path information translated into a physical path, e.g. "/usr/local/etc/httpd/htdocs/additional/stuff".

The Microsoft IIS is broken with respect to the translated path as well.

remote_host()

Returns either the remote host name or IP address. if the former is unavailable.

script_name() Return the script name as a partial URL, for self-refering scripts.

referer()

Return the URL of the page the browser was viewing prior to fetching your script. Not available for all browsers.

auth_type ()

Return the authorization/verification method in use for this script, if any.

server_name ()

Returns the name of the server, usually the machine's host name.

virtual_host ()

When using virtual hosts, returns the name of the host that the browser attempted to contact

server_port ()

Return the port that the server is listening on.

server_software ()

Returns the server software and version number.

remote_user ()

Return the authorization/verification name used for user verification, if this script is protected.

user_name ()

Attempt to obtain the remote user's name, using a variety of different techniques. This only works with older browsers such as Mosaic. Newer browsers do not report the user name for privacy reasons!

request_method()

Returns the method used to access your script, usually one of 'POST', 'GET' or 'HEAD'.

content_type()

Returns the content_type of data submitted in a POST, generally multipart/form-data or application/x-www-form-urlencoded

http()

Called with no arguments returns the list of HTTP environment variables, including such things as HTTP_USER_AGENT, HTTP_ACCEPT_LANGUAGE, and HTTP_ACCEPT_CHARSET, corresponding to the like-named HTTP header fields in the request. Called with the name of an HTTP header field, returns its value. Capitalization and the use of hyphens versus underscores are not significant.

For example, all three of these examples are equivalent:

   $requested_language = $q->http('Accept-language');
   $requested_language = $q->http('Accept_language');
   $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE');

https()

The same as http() , but operates on the HTTPS environment variables present when the SSL protocol is in effect. Can be used to determine whether SSL is turned on.

USING NPH SCRIPTS

NPH, or "no-parsed-header", scripts bypass the server completely by sending the complete HTTP header directly to the browser. This has slight performance benefits, but is of most use for taking advantage of HTTP extensions that are not directly supported by your server, such as server push and PICS headers.

Servers use a variety of conventions for designating CGI scripts as NPH. Many Unix servers look at the beginning of the script's name for the prefix "nph-". The Macintosh WebSTAR server and Microsoft's Internet Information Server, in contrast, try to decide whether a program is an NPH script by examining the first line of script output.

CGI.pm supports NPH scripts with a special NPH mode. When in this mode, CGI.pm will output the necessary extra header information when the header() and redirect() methods are called.

The Microsoft Internet Information Server requires NPH mode. As of version 2.30, CGI.pm will automatically detect when the script is running under IIS and put itself into this mode. You do not need to do this manually, although it won't hurt anything if you do. However, note that if you have applied Service Pack 6, much of the functionality of NPH scripts, including the ability to redirect while setting a cookie, b<do not work at all> on IIS without a special patch from Microsoft. See http://support.microsoft.com/support/kb/articles/Q280/3/41.ASP: Non-Parsed Headers Stripped From CGI Applications That Have nph- Prefix in Name.

In the use statement

Simply add the "-nph" pragmato the list of symbols to be imported into your script:

      use CGI qw(:standard -nph)

By calling the nph() method:

Call nph() with a non-zero parameter at any point after using CGI.pm in your program.

      CGI->nph(1)

By using -nph parameters

in the header() and redirect() statements:

      print $q->header(-nph=>1);

Server Push

CGI.pm provides four simple functions for producing multipart documents of the type needed to implement server push. These functions were graciously provided by Ed Jordan <ed@fidalgo.net>. To import these into your namespace, you must import the ":push" set. You are also advised to put the script into NPH mode and to set $| to 1 to avoid buffering problems.

Here is a simple script that demonstrates server push:

  #!/usr/local/bin/perl
  use CGI qw/:push -nph/;
  $| = 1;
  print multipart_init(-boundary=>'----here we go!');
  foreach (0 .. 4) {
      print multipart_start(-type=>'text/plain'),
            "The current time is ",scalar(localtime),"\n";
      if ($_ < 4) {
              print multipart_end;
      } else {
              print multipart_final;
      }
      sleep 1;
  }

This script initializes server push by calling multipart_init() . It then enters a loop in which it begins a new multipart section by calling multipart_start() , prints the current local time, and ends a multipart section with multipart_end() . It then sleeps a second, and begins again. On the final iteration, it ends the multipart section with multipart_final() rather than with multipart_end() .

multipart_init()
  multipart_init(-boundary=>$boundary);

Initialize the multipart system. The -boundary argument specifies what MIME boundary string to use to separate parts of the document. If not provided, CGI.pm chooses a reasonable boundary for you.

multipart_start()
  multipart_start(-type=>$type)

Start a new part of the multipart document using the specified MIME type. If not specified, text/html is assumed.

multipart_end()
  multipart_end()

End a part. You must remember to call multipart_end() once for each multipart_start(), except at the end of the last part of the multipart document when multipart_final() should be called instead of multipart_end().

multipart_final()
  multipart_final()

End all parts. You should call multipart_final() rather than multipart_end() at the end of the last part of the multipart document.

Users interested in server push applications should also have a look at the CGI::Push module.

Only Netscape Navigator supports server push. Internet Explorer browsers do not.

Avoiding Denial of Service Attacks

A potential problem with CGI.pm is that, by default, it attempts to process form POSTings no matter how large they are. A wily hacker could attack your site by sending a CGI script a huge POST of many megabytes. CGI.pm will attempt to read the entire POST into a variable, growing hugely in size until it runs out of memory. While the script attempts to allocate the memory the system may slow down dramatically. This is a form of denial of service attack.

Another possible attack is for the remote user to force CGI.pm to accept a huge file upload. CGI.pm will accept the upload and store it in a temporary directory even if your script doesn't expect to receive an uploaded file. CGI.pm will delete the file automatically when it terminates, but in the meantime the remote user may have filled up the server's disk space, causing problems for other programs.

The best way to avoid denial of service attacks is to limit the amount of memory, CPU time and disk space that CGI scripts can use. Some Web servers come with built-in facilities to accomplish this. In other cases, you can use the shell limit or ulimit commands to put ceilings on CGI resource usage.

CGI.pm also has some simple built-in protections against denial of service attacks, but you must activate them before you can use them. These take the form of two global variables in the CGI name space:

$CGI::POST_MAX

If set to a non-negative integer, this variable puts a ceiling on the size of POSTings, in bytes. If CGI.pm detects a POST that is greater than the ceiling, it will immediately exit with an error message. This value will affect both ordinary POSTs and multipart POSTs, meaning that it limits the maximum size of file uploads as well. You should set this to a reasonably high value, such as 1 megabyte.

$CGI::DISABLE_UPLOADS

If set to a non-zero value, this will disable file uploads completely. Other fill-out form values will work as usual.

You can use these variables in either of two ways.

1. On a script-by-script basis

Set the variable at the top of the script, right after the "use" statement:

    use CGI qw/:standard/;
    use CGI::Carp 'fatalsToBrowser';
    $CGI::POST_MAX=1024 * 100;  # max 100K posts
    $CGI::DISABLE_UPLOADS = 1;  # no uploads

2. Globally for all scripts

Open up CGI.pm, find the definitions for $POST_MAX and $DISABLE_UPLOADS, and set them to the desired values. You'll find them towards the top of the file in a subroutine named initialize_globals().

An attempt to send a POST larger than $POST_MAX bytes will cause param() to return an empty CGI parameter list. You can test for this event by checking cgi_error() , either after you create the CGI object or, if you are using the function-oriented interface, call <param()> for the first time. If the POST was intercepted, then cgi_error() will return the message "413 POST too large".

This error message is actually defined by the HTTP protocol, and is
designed to be returned to the browser as the CGI script's status
 code.  For example:

   $uploaded_file = param('upload');
   if (!$uploaded_file && cgi_error()) {
      print header(-status=>cgi_error());
      exit 0;
   }

However it isn't clear that any browser currently knows what to do with this status code. It might be better just to create an HTML page that warns the user of the problem.

COMPATIBILITY WITH CGI-LIB.PL

To make it easier to port existing programs that use cgi-lib.pl the compatibility routine "ReadParse" is provided. Porting is simple:

OLD VERSION
    require "cgi-lib.pl";
    &ReadParse;
    print "The value of the antique is $in{antique}.\n";

NEW VERSION
    use CGI;
    CGI::ReadParse
    print "The value of the antique is $in{antique}.\n";

CGI.pm's ReadParse() routine creates a tied variable named %in, which can be accessed to obtain the query variables. Like ReadParse, you can also provide your own variable. Infrequently used features of ReadParse, such as the creation of @in and $in variables, are not supported.

Once you use ReadParse, you can retrieve the query object itself this way:

    $q = $in{CGI};
    print $q->textfield(-name=>'wow',
                        -value=>'does this really work?');

This allows you to start using the more interesting features of CGI.pm without rewriting your old scripts from scratch.

AUTHOR INFORMATION

Copyright 1995-1998, Lincoln D. Stein. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

Address bug reports and comments to: lstein@cshl.example.com.org. When sending bug reports, please provide the version of CGI.pm, the version of Perl, the name and version of your Web server, and the name and version of the operating system you are using. If the problem is even remotely browser dependent, please provide information about the affected browers as well.

CREDITS

Thanks very much to:

Matt Heffron (heffron@falstaff.example.com.css.beckman.com)

James Taylor (james.taylor@srs.example.com.gov)

Scott Anguish <sanguish@digifix.com>

Mike Jewell (mlj3u@virginia.example.com.edu)

Timothy Shimmin (tes@kbs.example.com.citri.edu.au)

Joergen Haegg (jh@axis.example.com.se)

Laurent Delfosse (delfosse@delfosse.example.com.com)

Richard Resnick (applepi1@aol.example.com.com)

Craig Bishop (csb@barwonwater.example.com.vic.gov.au)

Tony Curtis (tc@vcpc.example.com.univie.ac.at)

Tim Bunce (Tim.Bunce@ig.example.com.co.uk)

Tom Christiansen (tchrist@convex.example.com.com)

Andreas Koenig (k@franz.example.com.ww.TU-Berlin.DE)

Tim MacKenzie (Tim.MacKenzie@fulcrum.example.com.com.au)

Kevin B. Hendricks (kbhend@dogwood.example.com.tyler.wm.edu)

Stephen Dahmen (joyfire@inxpress.example.com.net)

Ed Jordan (ed@fidalgo.example.com.net)

David Alan Pisoni (david@cnation.example.com.com)

Doug MacEachern (dougm@opengroup.example.com.org)

Robin Houston (robin@oneworld.example.com.org)

...and many many more...

for suggestions and bug fixes.

ÜBERSETZUNG

KaiSengpiel, perl-community.de; Mai 2005

A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT

        #!/usr/local/bin/perl

        use CGI;

        $anfrage = new CGI;

        print $anfrage->header;
        print $anfrage->start_html("Example CGI.pm Form");
        print "<h1> Example CGI.pm Form</h1>\n";
        &print_prompt($anfrage);
        &do_work($anfrage);
        &print_tail;
        print $anfrage->end_html;

        sub print_prompt {
           my($anfrage) = @_;

           print $anfrage->start_form;
           print "<em>What's your name?</em><br>";
           print $anfrage->textfield('name');
           print $anfrage->checkbox('Not my real name');

           print "<p><em>Where can you find English Sparrows?</em><br>";
           print $anfrage->checkbox_group(
                                 -name=>'Sparrow locations',
                                 -values=>[England,France,Spain,Asia,Hoboken],
                                 -linebreak=>'yes',
                                 -defaults=>[England,Asia]);

           print "<p><em>How far can they fly?</em><br>",
                $anfrage->radio_group(
                        -name=>'how far',
                        -values=>['10 ft','1 mile','10 miles','real far'],
                        -default=>'1 mile');

           print "<p><em>What's your favorite color?</em>  ";
           print $anfrage->popup_menu(-name=>'Color',
                                    -values=>['black','brown','red','yellow'],
                                    -default=>'red');

           print $anfrage->hidden('Reference','Monty Python and the Holy Grail');

           print "<p><em>What have you got there?</em><br>";
           print $anfrage->scrolling_list(
                         -name=>'possessions',
                         -values=>['A Coconut','A Grail','An Icon',
                                   'A Sword','A Ticket'],
                         -size=>5,
                         -multiple=>'true');

           print "<p><em>Any parting comments?</em><br>";
           print $anfrage->textarea(-name=>'Comments',
                                  -rows=>10,
                                  -columns=>50);

           print "<p>",$anfrage->reset;
           print $anfrage->submit('Action','Shout');
           print $anfrage->submit('Action','Scream');
           print $anfrage->endform;
           print "<hr>\n";
        }

        sub do_work {
           my($anfrage) = @_;
           my(@values,$key);

           print "<h2>Here are the current settings in this form</h2>";

           foreach $key ($anfrage->param) {
              print "<strong>$key</strong> -> ";
              @values = $anfrage->param($key);
              print join(", ",@values),"<br>\n";
          }
        }

        sub print_tail {
           print <<END;
        <hr>
        <address>Lincoln D. Stein</address><br>
        <a href="/">Home Page</a>
        END
        }

BUGS

Please report them.

SEE ALSO

CGI::Carp?, CGI::Fast?, CGI::Pretty?

-- HaraldBongartz - 06 Nov 2004
Topic attachments
I Attachment Action Size Date Who Comment
CGI.podpod CGI.pod manage 122.4 K 2005-06-11 - 14:42 KaiSengpiel Translation in progress 45%
Topic revision: r3 - 2005-06-11 - 14:42:42 - KaiSengpiel
 
Bitte die NutzungsBedingungen beachten.
Bei Vorschlägen, Anfragen oder Problemen mit dem PerlCommunityWiki bitten wir um WebBottomBarExample">Rückmeldung.