Unterthema: Apache-Konfiguration
Das Internet ist zum Massenmedium geworden; kaum ein Unternehmen, das nicht mehr oder minder nützliche Angebote im WWW bereitstellt. Intranets sind in Firmen auf dem Vormarsch, und immer mehr Privatleute leisten sich eine eigene Homepage.
Wenn man nun beginnt, seine Web-Seiten mit HTML zu erstellen, stößt man sehr schnell an die Grenzen dieser Sprache. Sinnvolle Anwendungen erfordern oftmals Interaktivität: Der Besucher einer Website macht Eingaben, tippt beispielsweise seinen Namen ein oder wählt Produkte aus einer Liste aus; die Website reagiert auf diese Eingaben, indem sie den Besucher mit seinem Namen anspricht oder ihm einen gefüllten Warenkorb präsentiert. Derartige Interaktivität läßt sich über das Common Gateway Interface (CGI) erreichen. Diese Schnittstelle ermöglicht eine Kommunikation zwischen dem Browser und dem Web-Server, die über das nackte Anfordern einer HTML-Seite hinausgeht.
Fragt der Browser hingegen nach einer URL der Art http://www.irgendwo.de/cgi-bin/script.cgi, erkennt ein entsprechend eingerichteter Server an der Endung `.cgi´, daß ein CGI-Skript angefragt wird. Während eine HTML-Datei das Aussehen einer WWW-Seite bestimmt, verbirgt sich hinter einem CGI-Skript ein Stück Programmcode, den der Web-Server ausführt. Häufig kommen Perl-Skripte zum Einsatz, da diese Skriptsprache einige Vorteile hinsichtlich der Kommunikation mit dem WWW-Server bietet; es ist aber auch jede andere Programmiersprache möglich.
Das CGI-Programm gibt dem Server normalerweise eine HTML-Seite mit den aufbereiteten Ergebnissen des Programmlaufs zurück. Handelt es sich beispielsweise um eine Suchanfrage, könnte diese Seite das Resultat der Suche tabellarisch auflisten. Der Server leitet diese aufbereiteten Ergebnisse dann an den Browser weiter.
Der Browser sendet also beispielsweise einen String wie http://www.irgendwo.de/cgi-bin/script.cgi?name=Larry%20Wall&adresse=Perlstr an den Server, der nun das CGI-Programm `script.cgi´ startet. Die Angaben nach dem `?´ übergibt er dabei als Argumente an das CGI-Programm; die HTML-Seite erzeugt diese Daten normalerweise mit Hilfe eines Formulars, in das der Anwender die benötigten Angaben einträgt. Das CGI-Skript nimmt die als Argumente übergebenen Daten auf und verarbeitet sie weiter. Anschließend erzeugt es eine HTML-Seite mit den Ergebnissen, die der Server an den Browser zurückschickt.
Um diesen Mechanismus zu nutzen, sind folgende Schritte nötig:
Für kleinere Anwendungen - etwa ein Intranet- oder kleiner Internet-Server - reicht ein PC mit einem solchen freien Web-Server vollkommen aus. Auch wenn Sie gar keinen eigenen WWW-Server betreiben wollen, sondern Ihre Web-Seiten bei einem Provider ablegen, empfiehlt es sich, die Seiten zuvor auf dem eigenen Rechner zu testen. Hierzu sind nicht einmal zwei vernetzte Rechner erforderlich: Zum Testen können Server und Browser auch auf einem Rechner laufen.
Viele Linux-Systeme starten Apache automatisch beim Booten, da die Online-Hilfe bei den meisten Distributionen über HTML-Dateien und CGI-Skripte realisiert ist (suchen Sie in der Ausgabe von ps -ax nach Prozessen mit dem Namen httpd - dahinter verbirgt sich der Apache). Wenn Sie im Browser die URL http://localhost/ beziehungsweise den Namen oder die IP-Adresse Ihres Rechners eingeben, landen Sie auf der (häufig von der Distribution eingerichteten) Startseite Ihres eigenen Apache. Die Programmiersprache Perl zum Erstellen von CGI-Skripten liegt allen Linux-Distributionen bei.
In aller Regel wird Ihre Linux-Distribution Apache bereits vernünftig vorkonfiguriert haben; die wichtigsten Einstellungen für CGI-Skripte sind im Kasten `Apache-Konfiguration´ zusammengefaßt. Große Teile der Apache-Konfiguration lassen sich komfortabel mit TkApache [3] oder dem Unix-Verwaltungs-Tool Webmin [4] erledigen. CGI-Skripte müssen unter Unix übrigens ausführbare Dateien sein.
Unter Windows müssen Sie zunächst einen Web-Server installieren. Apache für Win32 erwies sich bei uns im Betrieb als etwas störrisch - das Programm hat noch Beta-Status; außerdem dürfte die Unix-typische Konfiguration über Textdateien GUI-verwöhnten Windows-Fans recht umständlich vorkommen.
Sambar hingegen läßt sich problemlos installieren und durch seine Web-basierte Administrationsoberfläche recht einfach konfigurieren. Das Paket enthält bereits einen Perl-Interpreter. Wer sich ernsthaft mit der CGI-Programmierung in Perl beschäftigen will, wird sich allerdings trotzdem eine aktuelle Win32-Portierung von Perl besorgen müssen [5] - Sambars Perl kommt nämlich ohne die zahllosen Bibliotheken, die die Perl-Programmierung deutlich erleichtern. Viele der nützlichen Perl-Skripte, die man im Internet findet, setzen diese Bibliotheken voraus. Eine unerschöpfliche Quelle für Skripte, Hilfen und Dokumentation ist das Comprehensive Perl Archive Network CPAN [6].
Auch Sambar läßt sich ohne aktive Internet-Verbindung mit einem Browser ansprechen, der auf dem gleichen Rechner läuft - als URL gibt man http://localhost/ (oder die entsprechende IP-Nummer 127.0.0.1) an. Der Browser präsentiert dann die Startseite von Sambar, von wo aus Sie über Links die Dokumentation und die Administrationsseite erreichen. Hier sollten jedoch erst einmal keine Änderungen nötig sein.
Mit dem <FORM>-Tag lassen sich Formulare in HTML-Seiten einbinden. Der typische Beginn eines Formularfeldes sieht so aus:
<FORM ACTION="/cgi-bin/script.cgi" METHOD="POST">`ACTION´ spezifiziert das auszuführende Skript (inklusive des Namens des cgi-bin-Verzeichnisses); `METHOD´ legt fest, wie der Browser die Daten an den Server übergibt - und bestimmt damit auch, wie das CGI-Programm an die Daten kommt.
Zur Auswahl stehen zwei Methoden. Bei `GET´ hängt der Browser die Formulardaten einfach an die URL des Skripts an; ein `?´ trennt den Skriptnamen von den Daten. Der Server legt die Daten in der Umgebungsvariablen QUERY_STRING ab, aus der sie das Skript auslesen kann. Bei `POST´ hingegen liest das CGI-Skript die Daten von der Standardeingabe - genau so, als würde der Anwender die erwarteten Daten nacheinander eintippen. Die verwendete Methode kann das Skript anhand der Umgebungsvariablen REQUEST_METHOD erkennen.
Als grobe Richtlinie zur Verwendung: `GET´ können Sie verwenden, wenn Sie nur kurze Daten senden möchten, beispielsweise eine EMail-Adresse oder einen einfachen Suchstring - die meisten WWW-Server verkraften nicht mehr als 512 Zeichen in der URL. Erfaßt ein Formular vielfältige Daten, die eine flexible Länge erreichen können (wie etwa die Kommentare für ein Gästebuch), sollte man `POST´ wählen.
Eingerahmt von den Tags <FORM> und </FORM> lassen sich verschiedene Elemente zur Eingabe von Daten verwenden: ein- und mehrzeilige Textfelder, Auswahllisten, Radio-Buttons, Checkboxen und Menüs. All diese Formularfelder werden nur innerhalb des <FORM>- Tags sichtbar.
<INPUT TYPE="text" SIZE="30" NAME="eingabe">beispielsweise erzeugt ein einzeiliges Textfeld, das der Browser mit einer Breite von 30 Zeichen darstellt. Der `NAME´ dient zur Identifikation der verschiedenen INPUT-Felder, indem er dem Eingabeelement einen Variablennamen zuordnet. Anhand dieser Bezeichner sortiert das CGI-Skript die Daten später auseinander.
<INPUT TYPE="submit" VALUE="abschicken">dient dazu, die Formulardaten zum Server zu übertragen. Die Zeile erzeugt einen mit `Abschicken´ beschrifteten Button. Klickt der Anwender auf diesen Button, sendet der Browser den Namen des CGI-Skripts und die im Formular eingegeben Daten an den Server.
Sie können ein Skript auch über einen Link wie <A HREF="/cgi-bin/skript.cgi"> oder im Header einer HTML-Datei bei Aufruf der Seite direkt ausführen lassen, etwa um dem Anwender eine Startseite mit aktueller Information zu präsentieren:
<META HTTP-EQUIV="refresh" CONTENT="0; URL=/cgi-bin/welcome.cgi">.Das Skript welcome.cgi könnte beispielsweise eine HTML-Seite mit Informationen über die aktuelle Serverlast, Datum und Uhrzeit erzeugen oder die neuesten Sonderangebote aus einer Datenbank abfragen und in die Begrüßungsseite einfügen.
Es ist auch möglich, mehrere Formulare mit unterschiedlichen CGI-Skripten auf einer HTML-Seite einzubinden - dazu müssen die Tags <FORM> und </FORM> lediglich mehrfach auf der Seite auftauchen.
<INPUT TYPE="password" MAXLENGTH="8" SIZE="30" NAME="passwort">erzeugt ein Paßwortfeld, in dem die Eingaben unsichtbar bleiben. Der Browser stellt es mit einer Breite von 30 Zeichen dar, das Feld nimmt aber höchstens acht Zeichen an. Das Paßwort in diesem Feld wird übrigens als Klartext über das Internet gesendet, es bietet also keine echte Sicherheit. Wenn Sie sichere Paßwörter benötigen, müssen Sie entweder Secure Sockets Layers (SSL [11]) verwenden oder auf die Paßwortabfragen zurückgreifen, die der Web-Server bietet (Apache beispielsweise über die .htaccess-Dateien).
Mit <INPUT TYPE="radio"> erzeugt man eine Auswahl, in der sich der Anwender für eine Alternative entscheiden muß - im Gegensatz zu Checkboxen, wo man mehrere Alternativen gleichzeitig anwählen kann:
<INPUT TYPE="radio" NAME="geschlecht" VALUE="Mann"> Mann <BR> <INPUT TYPE="radio" NAME="geschlecht" VALUE="Frau"> Frau <INPUT TYPE="checkbox" NAME="pc" VALUE="ja"> PC <BR> <INPUT TYPE="checkbox" NAME="modem" VALUE="ja"> ModemAuch hier bezeichnet `NAME´ wieder die Variable, der je nach Auswahl der Wert in `VALUE´ zugewiesen wird.
Das Eingabe-Element `reset´ schließlich erzeugt einen Button, dessen Betätigung alle Eingaben im Formular löscht:
<INPUT TYPE="reset" VALUE="löschen">Weitere Formular-Elemente sind mehrzeilige Textfelder und Auswahllisten, die man jedoch nicht über <INPUT>, sondern über eigene Tags erzeugt:
<TEXTAREA NAME="kommentar" rows=3 cols=40></TEXTAREA>generiert ein Textfeld, das der Browser mit drei Zeilen à 40 Zeichen darstellt und mit Scrollbars versieht. Der eingegebene Text wird hier der Variablen `kommentar´ zugewiesen.
Auswahllisten erstellt man mit dem <SELECT>-Tag. Auch hier bezeichnet `NAME´ die Variable, die die Auswahl zur Auswertung in einem CGI-Skript speichert.
<SELECT NAME="user" SIZE=1> <OPTION>Hacker <OPTION>normaler User <OPTION>Einsteiger </SELECT>
Natürlich kann auch ein CGI-Skript Formulare als Ausgabe erzeugen, um beispielsweise eine Auswahlliste zu generieren, deren Inhalt von einem zuvor ausgewählten Interessengebiet abhängt.
Perl ist für die Verarbeitung von Zeichenketten besonders gut geeignet - ideal, um beispielsweise die Ausgabe einer Datenbankabfrage auszuwerten und in eine übersichtliche HTML-Seite umzusetzen. Perl ist für nahezu jede Plattform erhältlich. Die Perl-Bibliothek CGI.pm [7] bietet Funktionen, die speziell die Erstellung von CGI-Skripten erleichtern. Dieses Modul läßt sich sowohl in Perls neuer, objektorientierter Syntax als auch in der `klassischen´, funktionalen Schreibweise verwenden.
Derzeit im Aufschwung ist die objektorientierte Skriptsprache Python, die ebenfalls viele CGI-Ergänzungen bietet. Sehr praktisch und schnell ist die Sprache PHP, die direkt in eine HTML-Datei eingebettet und dann von einem Modul des Web-Servers ausgeführt wird.
Alle drei Skriptsprachen bieten einen vergleichbaren Funktionsumfang, verfügen über Schnittstellen zu SQL-Datenbanken und bringen Bibliotheken mit, die es dem Anwender leichter machen, CGI-Skripte zu erstellen. Sie können Ihre CGI-Programme aber theoretisch auch in Visual Basic, C oder als Shellskript schreiben.
Welche Sprache auch immer zum Einsatz kommt: Das CGI-Programm liest die Variablen des Formulars von der Standardeingabe (sofern das Formular die Daten mit der Methode `POST´ überträgt) und gibt die Ergebnisse als HTML-Seite an den Server zurück, indem es HTML-Code auf die Standardausgabe schreibt.
Es kann sicher nicht schaden, CGI-Skripte fremder Herkunft - etwa aus dem Internet - zunächst zu überprüfen, bevor man sie einsetzt; immerhin können CGI-Skripte Systemprogramme starten und auf die Dateien des Servers zugreifen, und auch ohne root-Privilegien ist einiges an Unfug möglich [12].
CGI-Skripte sollten die übergebenen Daten des Formulars generell auf Sonderzeichen wie `..´, `/´ beziehungsweise `\´ oder `.´ überprüfen - dahinter könnte der Versuch eines Anwenders stehen, über das CGI-Skript Programme auf dem Server zu starten [12]. Ein ordentlich programmiertes Skript liefert in diesem Fall eine HTML-Seite mit einer freundlichen Fehlermeldung zurück.
Kritische Aktionen wie das Ändern von Systempaßwörtern erledigt man am besten gar nicht via CGI-Skript. Wenn das Skript Dateien auf dem Web-Server manipuliert (etwa in eine Textdatei schreibt), empfiehlt es sich, diese Datei in einem Verzeichnis abzulegen, auf das nur der Web-Server Zugriff hat.
Schließlich darf man nicht vergessen, daß die gesamte Kommunikation zwischen Server und Browser unverschlüsselt erfolgt und daher leicht abgehört werden kann. Wer eine wirklich sichere Datenübertragung zwischen Client und Server benötigt, muß auf das SSL-Modul (Secure Socket Layers) für Web-Server zurückgreifen, das die Kommunikation über das Internet verschlüsselt [11].
Seit der Version 5.004 liefert Perl das Modul CGI.pm [7] mit, das hilfreiche Funktionen für CGI-Skripte bereitstellt - beispielsweise einfach zu benutzende Subroutinen zur Dekodierung der Eingabedaten des Skriptes. Einen guten Einstieg in Perl bietet [8]; [9] geht speziell auf die Erfordernisse der CGI-Programmierung ein.
Wer schon einmal C programmiert oder unter Unix mit Shellskripten hantiert hat, wird sich in Perl schnell heimisch fühlen: Perl hat viele Konstrukte aus C übernommen und sich bei klassischen Unix-Tools wie sed, awk und grep bedient. Herausgekommen ist eine Skriptsprache, die zwar relativ leicht zu erlernen ist, deren effektiver Einsatz aber doch einige Kenntnisse und etwas Erfahrung erfordert.
Perl ist eine interpretierte Sprache; ein Perl-Skript ist daher langsamer als ein kompiliertes Programm. Bei CGI-Skripten spielt das jedoch meist keine Rolle, da die Antwortzeiten eines Web-Servers stärker von der Bandbreite im Netz oder der Auslastung des Servers abhängen.
Unter Unix beginnt ein Perl-Skript mit der Zeile `#!/usr/bin/perl -wT´. Diese erste Zeile weist die Shell an, das Skript zur Ausführung an den Perl-Interpreter weiterzureichen - genau so, wie die Zeile `#!/bin/sh´ ein Shell-Skript kennzeichnet, das von der Standard-Unix-Shell `sh´ abgearbeitet wird. Den Pfad zum Perl-Interpreter müssen Sie an die Gegebenheiten Ihres Systems anpassen. Perl-Skripte müssen mit dem chmod-Kommando ausführbar gemacht werden.
Die Option `-w´ bewirkt erweiterte Warnungen des Interpreters, `-T´ schaltet den sogenannten `Taint-Modus´ an [12]. In diesem Sicherheitsmodus darf das Perl-Skript keine Operationen durchführen, die die Systemsicherheit beeinträchtigen könnten - für CGI-Skripte sehr empfehlenswert. Beispielsweise darf ein Skript im Taint-Modus `von außen´ eingelesene Werte nicht ohne vorherige Überprüfung weiterverarbeiten.
Unter Windows startet man Perl-Skripte entweder über einen expliziten Aufruf des Perl-Interpreters mit `c:\perl5\bin\perl.exe myscript.pl´, oder man definiert im Explorer eigene Dateitypen für Perl- und CGI-Skripte, die mit einem Aufruf des Perl-Interpreters assoziiert werden. Dateien mit der Extension `.pl´ oder `.cgi´ werden dann standardmäßig vom Perl-Interpreter ausgeführt und lassen sich direkt von der Kommandozeile aus oder durch einen Doppelklick im Explorer starten.
Die unter Unix erforderliche erste Zeile mit der Angabe des Perl-Interpreters darf unter Windows fehlen. Ist sie jedoch vorhanden, wertet Perl die dort angegebenen Argumente für den Perl-Interpreter aus. Eine erste Zeile wie `#!/usr/bin/perl -T´ aktiviert also auch unter Windows den sicheren `Taint-Modus´.
Perl kennzeichnet seine unterschiedlichen Variablentypen durch verschiedene Sonderzeichen, die dem Variablennamen vorangestellt sind. Perl kennt Skalare, Arrays und Hashs, die durch ein `$´, `@´ beziehungsweise `%´ vor dem Namen unterschieden werden.
$var ist ein Skalar, ein einzelner Wert, der entweder ein numerischer Wert oder eine Zeichenkette sein kann. Eine Variable existiert, sobald man ihr einen Wert zuweist:
$zahl = 42; # Numerischer Wert 42 $string = "42"; # String `42´Zeichenketten wie Worte, Sätze, Buchstaben und Ziffernfolgen werden durch einfache (') oder doppelte (") Anführungszeichen eingerahmt, und man vergleicht sie mit den Operatoren `eq´ und `ne´ (equal und non-equal); zum Vergleich von Zahlen (also numerischen Werten) dienen `==´ und `!=´ (gleich und ungleich).
Wenn eine Zeichenkette von doppelten Anführungszeichen umschlossen ist, ersetzt Perl enthaltene Variablennamen durch ihren Wert; Strings zwischen einfachen Anführungszeichen übernimmt Perl `wörtlich´, ohne den Inhalt in irgendeiner Weise zu interpretieren. Das Skript
$name = "Bond"; print "Mein Name ist $name\n",´Mein Name ist $name\n´;führt zu der Ausgabe
Mein Name ist Bond Mein Name ist $name\nDas `\n´ steht für Newline und erzeugt einen Zeilenumbruch - sofern es von Perl interpretiert wird.
Die Backticks (`) haben übrigens eine ganz andere Bedeutung: Perl reicht von Backticks eingeschlossene Strings als Kommando an die Shell weiter, wobei Variablennamen durch die Werte der Variablen ersetzt werden. Rückgabewert ist die Ausgabe des Kommandos.
Möchte man, daß Perl ein Sonderzeichen innerhalb einer mit " umschlossenen Zeichenkette `wörtlich´ interpretiert, muß man ihm einen Backslash (`\´) voranstellen:
print "ein Klammeraffe: \@";
@array = ("Hund", $Katze, ´Maus´);
Arrays zählen in Perl ab 0; die Anweisung
print "$array[0]";führt zur Ausgabe von `Hund´. Der Ausdruck `$#array´ liefert den Index des letzten Elementes im Array, im Beispiel also 2. Die Anzahl der Elemente in einem Array beträgt daher `$#array+1´ - wichtig, wenn man beispielsweise in einer `for´-Schleife alle Array-Elemente bearbeiten möchte.
Benötigt man Schlüssel-/Wert-Paare, verwendet man ein Hash oder assoziatives Array, das mit dem Zeichen `%´ gekennzeichnet wird. Hashs sind unsortierte Listen, aus denen Sie die gewünschten Daten über einen selbstdefinierten Schlüssel (statt der Zahlen 0, 1, 2 ... bei `normalen´ Arrays) herausgreifen:
%hash = (´Tier´ => ´Katze´, ´Haus´ => ´roter Bungalow´);
print $hash{"Tier"}, "\n";
gibt einfach `Katze´ aus.
open (INFILE, "/etc/passwd"); @inhalt = <INFILE>; close (INFILE);lesen alle Zeilen aus /etc/passwd und legen sie in dem Array @inhalt ab. Dieses Beispiel gibt Ihnen vielleicht schon einen Eindruck von der Effizienz, mit der sich Textdateien in Perl bearbeiten lassen.
Um eine Datei zum Beschreiben zu öffnen, setzt man dem Dateinamen einfach ein `>´ voran:
open (OUTFILE, ">temp");öffnet die Datei `temp´ zum Beschreiben. Um in diese Datei zu schreiben, übergibt man der Funktion print das Filehandle als erstes Argument:
print OUTFILE "erste Zeile";Neben dem `<>´-Operator zum zeilenweisen Lesen kennt Perl auch die Funktion read (FILEHANDLE, $puffer, $n), die n Zeichen aus FILEHANDLE liest und in $puffer ablegt. Sie gibt die Anzahl gelesener Zeichen zurück. Perl verfügt über weitere Funktionen zum Lesen einzelner Zeichen (getc) und zur Schreib- und Lesepositionierung in einer Datei (seek).
Perl kennt keine Pointer; Sie können also keinen Speicherbereich gezielt reservieren oder freigeben. Um die gesamte Speicherverwaltung kümmert sich Perl selbst. Variablen sind in Perl global gültig - auch temporär gedachte Variablen wie ein $i als Zähler in einer for-Schleife. Sollen Variablen nur in einer Subroutine, Schleife oder Anweisung gültig sein, muß man ihnen ein `my´ voransetzen:
for (my $i=0; $i<$n; $i++)
$zeile = <FILEHANDLE>; @zeile = <FILEHANDLE>;Der `<>´-Operator liest beide Male zeilenweise aus der Datei, auf die FILEHANDLE verweist; aber im skalaren Kontext ($zeile) nur eine Zeile, im Listenkontext hingegen alle Zeilen der Datei. Wenn man in einer Schleife nacheinander alle Zeilen einer Datei einlesen möchte und versehentlich die zweite Form wählt, kann man lange suchen, wieso das Skript auch bei einer langen Datei lediglich einmal liest und dann behauptet, die Datei sei zu Ende ...
Gerade bei Arrays stößt man immer wieder auf solche Probleme:
@daten = @liste;kopiert ein Array in ein anderes;
$daten = @liste;hingegen weist der skalaren Variablen $daten einen skalaren Wert zu - nämlich die Anzahl der Elemente in @liste.
In einigen Zusammenhängen dürfen Sie in Perl nur skalare Werte verarbeiten; beispielsweise müssen die Werte in einem Hash Skalare sein. Möchte man eine Liste als Wert über einen Schlüssel in einem Hash greifbar machen, muß man eine Referenz auf die Liste erzeugen:
$referenz = \@alte_liste;Eine solche Referenz ist ein Skalar, darf also als Wert einem Schlüssel in einem Hash zugewiesen werden. Um auf die Werte der Liste zuzugreifen, muß man die Referenz wieder dereferenzieren:
@neue_liste = @$referenz;Das `@´ vor dem `$referenz´ weist Perl an, die skalare Referenz als Liste zu dereferenzieren.
Eine Reihe von Funktionen erleichtern das Bearbeiten von Listen, da sie dem Programmierer das Hantieren mit den Indizes ersparen. push @liste1, @liste2 hängt die Elemente von @liste2 an das Ende von @liste1 an, pop @liste entfernt das letzte Element von @liste. unshift und shift arbeiten analog am Anfang der Liste. splice schneidet Bereiche aus einer Liste aus. sort sortiert eine Liste, reverse kehrt sie um. keys %hash erzeugt eine Liste, die alle Schlüssel eines Hashs enthält; values macht dasselbe mit den Werten.
Reguläre Ausdrücke bieten eine abstrakte Möglichkeit, Dinge zu formulieren wie `Alle Dateinamen, die mit einer Zahl beginnen und mit z enden´ oder `Alle Zeilen, in denen auf einen Punkt kein Leerzeichen folgt´. Den vielfältigen Möglichkeiten steht eine entsprechend komplexe Syntax gegenüber, die in [10] bis ins letzte Detail erläutert ist.
Reguläre Ausdrücke werden durch zwei Schrägstriche (`/´) eingeschlossen; zwischen den `/´ dürfen auch Variablen stehen. Sie verwenden Metazeichen, um bestimmte Bedingungen zu formulieren: So steht ein `+´ für ein- oder mehrfaches Vorkommen des unmittelbar davorstehenden Zeichens, ein `*´ für null- oder mehrfaches Vorkommen, ein `?´ für null- oder einfaches Vorkommen. `{n}´ findet ein Zeichen, das genau n-mal wiederholt wird.
Der reguläre Ausdruck /ab*c+d?e{3}/ beispielsweise paßt auf eine Zeichenfolge, die mit `a´ beginnt; anschließend dürfen beliebig viele (oder auch gar kein) `b´ folgen. Das nächste Zeichen muß ein `c´ sein, das beliebig oft wiederholt sein darf und dem höchstens ein `d´ folgen darf. Daran müssen sich genau drei `e´ anschließen.
Sollen sich diese Quantifizierer nicht nur auf ein Zeichen, sondern eine ganze Zeichenfolge beziehen, muß diese Zeichenfolge eingeklammert werden. /ab{3}/ sucht nach einem `a´ vor drei `b´, /(ab){3}/ hingegen nach einem dreimaligen Vorkommen von `ab´.
Weitere Metazeichen stehen für den Anfang (`^´) und das Ende der Zeichenfolge (`$´). Ein `.´ paßt auf jedes beliebige Zeichen außer dem Zeilenende. Auf eine Zeichenfolge, die von `[]´ umschlossen ist, paßt jedes Zeichen innerhalb der Zeichenfolge: /^[01]$/ findet Zeichenketten, die aus genau einem der beiden Zeichen `0´ oder `1´ bestehen. /[a-z]/ paßt auf alle Zeichenfolgen, die irgendeinen Kleinbuchstaben zwischen `a´ und `z´ enthalten. Übrigens: Die Bereichsangabe entspricht der Reihenfolge der Zeichen im Zeichensatz; /[a-z]/ umfaßt also keine Umlaute.
`|´ trennt alternative Suchausdrücke: /xyz|XYZ/ paßt auf Strings, die die Zeichenfolge `xyz´ entweder in Klein- oder Großbuchstaben enthalten. Möchte man nach Metazeichen selbst suchen, müssen diese mit einem vorangestellten `\´ quotiert werden.
Der Operator `=~´ dient dazu, einem regulären Ausdruck den String zu übergeben, der durchsucht werden soll. Das Ergebnis der Suche ist TRUE, wenn der Suchausdruck auf den String paßt. Die folgenden Anweisungen geben die Zeichenkette $str nur dann aus, wenn sie mit `a´ beginnt:
if ($str =~ /^a/)
{
print "$str\n";
}
s/.*name/Der Name ist/ersetzt die gesamte Zeichenkette bis zum String `name´ (inklusive) durch `Der Name ist´; der Rest der Zeichenfolge bleibt erhalten.
Bei derartigen Aufgaben stößt man jedoch auf ein Problem: Reguläre Ausdrücke sind `greedy´ (gierig); das heißt, in dem Beispiel würde der gesamte String bis zum letzten Vorkommen von `name´ ersetzt (sofern diese Zeichenfolge mehrfach vorkommt). Da dieses Verhalten nicht immer erwünscht ist, besitzt Perl eine raffinierte Erweiterung: Steht hinter einem Quantifizierer ein `?´, deckt der Ausdruck so wenige Zeichen wie möglich ab. Der Ausdruck
s/.*?name/Der Name ist/würde also die Zeichenkette bis zum ersten Vorkommen von `name´ ersetzen.
Möchte man alle Vorkommen einer Zeichenfolge innerhalb eines Strings ersetzen, muß man an den regulären Ausdruck die Option `g´ anhängen:
s/Hase/Igel/gersetzt alle Hasen durch Igel. Ohne das `g´ an Ende würde lediglich der erste Hase zum Igel. Eine weitere nützliche Option zum Anhängen ist `i´: In diesem Fall wird die Groß-/Kleinschreibung nicht berücksichtigt.
Häufig möchte man die gefundenen Strings weiterverarbeiten. Zeichenketten, die auf eingeklammerte reguläre Ausdrücke passen, weist Perl automatisch den Variablen $1, $2 und so weiter zu. Angenommen, Sie möchten aus einer Zeile wie `Name: Bond; Vorname: James; Beruf: ...´ den Nach- und Vornamen extrahieren und weiterverarbeiten, so gelingt das mit folgendem Ausdruck:
/Name: ([a-zA-Z]+); Vorname: ([a-zA-Z]+)/$1 enthält anschließend `Bond´, $2 `James´.
Das Array @ARGV sammelt alle Kommandozeilen-Parameter, die dem Skript übergeben wurden. Im Gegensatz zu C ist $ARGV[0] nicht der Name des Skriptes - der steht ja schon in $0 -, sondern das erste Kommandozeilenargument.
Die Parameter, die das Hauptprogramm an eine Subroutine übergibt, finden sich in dem Array @_. Ruft man ein Unterprogramm adresse in der Form
&adresse($name, $vorname, $telefon);auf, findet es $name in $_[0], $vorname in $_[1] und so weiter. Generell nimmt ein Unterprogramm eine Liste als Argument entgegen und gibt eine Liste zurück. Der Programmierer braucht die Übergabeparameter der Subroutine nicht explizit zu deklarieren:
sub adresse
{
# Aktionen der Subroutine
}
genügt, um eine Subroutine mit beliebigen Parametern zu deklarieren. Gibt ein Unterprogramm eine Fehlermeldung zurück, findet sie das Hauptprogramm in der Variablen $!.
Sehr hilfreich in Schleifen ist $_. In einer while-Schleife enthält $_ das gerade aktuell bearbeitete Element:
while(<FILEHANDLE>)
{
print $_;
}
gibt alle Zeilen der Datei FILEHANDLE aus. In diesem Fall könnte man sogar das $_ nach der print-Anweisung weglassen, da Perl davon ausgeht, daß sich Aktionen in einer Schleife auf $_ beziehen, sofern nicht ausdrücklich etwas anderes gewünscht wird:
open (FILE, `/etc/passwd´);
while (<FILE>)
{
if (/schmidt/i) { print; }
}
gibt unter Unix den Eintrag des Users `schmidt´ (wegen des angehängten `i´ in Klein- oder Großbuchstaben) aus der Paßwortdatei aus. Die einzelnen Elemente einer Liste lassen sich mit `foreach @liste´ abarbeiten. Auch hier erhält $_ bei jedem Schleifendurchlauf den Wert des nächsten Elementes von @liste.
Weitere wichtige Variablen sind %ENV, ein Hash mit dem Inhalt der Umgebungsvariablen. $ENV{´PATH´} beispielsweise liefert den Programmpfad zurück. Für CGI-Skripte wichtige Umgebungsvariablen, die der Web-Server setzt, sind $ENV{´REQUEST_METHOD´} - entweder GET oder POST - und $ENV{´QUERY_STRING´}, die bei GET die Daten der HTML-Seite enthält.
In der nächsten Folge geht es dann ans Eingemachte: Eine netzwerkfähige Adreßdatenbank, vollständig in Perl und HTML realisiert, wird Ihnen zeigen, wie das Zusammenspiel zwischen Web-Server und Browser in der Praxis funktioniert. (odi)
[2] www.sambar.com
[3] www.eunuchs.org/linux TkApache/index.html
[4] www.webmin.com/webmin/
[5] www.perl.com
[6] www.perl.com/CPAN
[7] http://stein.cshl.org/WWW/software/CGI/
[8] Rainer Krienke, Programmieren in Perl, Hanser, 1998
[9] Shishir Gundavaram, CGI-Programmierung im World Wide Web, O´Reilly, 1996
[10] Jeffrey Friedl, `Reguläre Ausdrücke´, O´Reilly, 1997
[11] www.netscape.com/products/security/ssl
[12] Karsten Meier, Zugestopft, Vermeiden von Sicherheitslöchern in CGI-Skripten, c't 6/98, S. 346
# To use CGI scripts: AddHandler cgi-script .cgiApache benötigt den absoluten Pfad, in dem die CGI-Skripte liegen (`realname´), sowie die Pfadangabe, unter der die Skripte in HTML-Seiten angesprochen werden (`fakename´):
# ScriptAlias: This controls which directories contain server scripts. # Format: ScriptAlias fakename realname ScriptAlias /cgi-bin/ /usr/local/apache/share/cgi-bin/Unter Windows lautet der `echte´ Verzeichnisname `C:/Programme/Apache Group/Apache/cgi-bin´. Beachten Sie, daß Apache in Pfadangaben auch unter Windows den Unix-typischen Slash `/´ verlangt!
In access.conf schließlich sollte man restriktive Zugangsbedingungen für das Verzeichnis cgi-bin festlegen, um keine Sicherheitslücken entstehen zu lassen. Das hinter dem Schlüsselwort `Directory´ angegebene Verzeichnis ist das auch bei `ScriptAlias´ genannte.
# /usr/local/apache/share/cgi-bin should be changed to whatever your SkriptAliased # CGI directory exists, if you have that configured. <Directory /usr/local/apache/share/cgi-bin> AllowOverride None Options None </Directory>