Entwicklungsumgebung
Aufgabenstellung
Script Header schreiben
Libraries verwenden und Script strukturieren
Unterfunktionen schreiben
CGI auf Webserver installieren
Ausblick
Entwicklungsumgebung
PERL CGI's welche auf einem LINUX Server laufen sollen in einer Win32 Umgebung entwickeln? Jawohl das geht! Und wer Wert darauf legt, dass seine Scripte ohne Änderung gleichermassen auf Win32 und LINUX laufen müssen, sollte zumindest die im Folgenden beschriebenen Besonderheiten kennen:
- Unter LINUX gibt es keine Laufwerksbuchstaben! Bei der Entwicklung eines CGI's in einer Win32 Umgebung kann die Laufwerksangabe entfallen sofern sich HTTP Root, CGI-BIN und andere lokale Pfade auf ein und demselben Laufwerk befinden.
- Unter LINUX gibt es den Slash! Für PERL kein Problem in einer Win32 Umgebung, einfach den Slash verwenden (lediglich mit einigen Win32 Modulen muss der Backslash verwendet werden, dann jedoch bitte maskieren).
- Sollen Systembefehle eingesetzt werden, ist zu beachten, dass diese selbstverständlich von System zu System unterschiedlich sind. Mit dem geschickten Einsatz von diversen PERL Modulen lassen sich jedoch manche Systembefehle durch reines PERL ersetzen und das Script erhält somit eine Plattformunabhängigkeit.
- Soll ein Script auch mit verschiedenen Systembefehlen plattformunabhängig gemacht werden, kann die Version des Betriebssystems über die Variable $^O in Kontrollstrukturen aufgearbeitet werden.
Voraussetzung für das lokale Testen von PERL CGI's ist ein installierter lokaler
Webserver möglichst mit virtuellen Hosts die beim Offline Testen von URL übergreifenden Scripts sehr von Vorteil sind. Bei der Auswahl der Serversofware ist u.a. der Gedanke interessant inwieweit der Pfad zum PERL Interpreter (1. Zeile eines jeden Scripts) angegeben werden muss, weil dieser mit Sicherheit in einer Win32 Umgebung anders ist als unter LINUX. Soll ein Script also nicht jedesmal vor dem Hochladen in dieser Zeile geändert werden müssen, sollte ein für lokale Tests ein Webserver genommen werden der die 1. Zeile ignoriert wie z.B. der
OmniHTTPd. Der PERL Interpreter ist erhältlich bei
Activestate. Schließlich ist auch noch die Wahl eines geeigneten Editors zu treffen, z.B.
Ultraedit.
Aufgabenstellung
Zu Scripten ist ein CGI welches einmal die HTML Seite aufbaut und zum Anderen die Verarbeitung der Eingaben übernimmt. Die Eingaben sollen zeilenweise in eine Datei geschrieben werden mit dem folgenden Aufbau:
|
datum und zeit;name;geschlecht;alter
|
Während das Geschlecht aus einer Option Bar ausgewählt werden kann und demzufolge immer ein Wert gegeben ist, müssen Name und Alter stets vom Benutzer ausgefüllt werden. Bei fehlenden Eingaben soll das Script eine Fehlermeldung ausgeben.
Script Header schreiben
Die allererste Zeile eines jeden PERL Scripts enthält den Pfad zum PERL Interpreter (es sei denn der Webserver ignoriert Diese). Syntax:
Die nächsten Zeilen sollten in keinem Script fehlen und werden als Kommentar notiert:
# Verwendungszweck
# Autor
# Erstellungsdatum
# Version
|
Der nächste Block beinhaltet globale Variablen welche vom Benutzer zu setzen sind, da dieses Script eine Datei beschreibt muss der Benutzer den lokalen Pfad und Dateinamen angeben
# Pfad und Name der Benutzerdatei
$ben_dat = "/temp/benutzer.txt";
|
Libraries verwenden und Script strukturieren
Lesen und Parsen von HTML Form's lassen sich erheblich vereinfachen mit Modulen oder Libraries. Im Vorliegenden Fall soll die
cgi-lib.pl für diesen Zweck verwendet werden. Ohne die Funktionen jetzt gleich mit Quelltext zu definieren, kann nun die komplette Struktur der CGI's locker aufgegliedert notiert werden:
require "cgi-lib.pl";
print &PrintHeader; # der Content-type...
if ( &ReadParse ) { # Wenn eine Eingabe erfolgte...
&einprf; # Eingabe prüfen
&a_html; # Seite bis Body
&write_file; # Datei anlegen und Einträge in Datei schreiben
&quit; # erfolgreiche Eingaben im Browser anzeigen
&z_html; # Seite schließen
}
else{ # keine Eingabe, Seite aufbauen mit Formular
&a_html; # Seite bis Body
&form; # Eingabeformular
&z_html; # Seite schließen
}
exit;
|
Kleine Erläuterung zu diesem Script bisher
Mit require "cgi-lib.pl"; wird Selbige eingebunden. Die nächste Zeile schickt den Content-Type:text/html zum Browser gefolgt von einer Leerzeile (wichtig).
Die nachfolgende Kontrollstruktur beinhaltet den Ablauf des CGI's in 2 Blöcken, einmal im Falle einer Benutzereingabe und zum Anderen im Falle dass noch keine Eingabe erfolgte. Diese Kontrollstruktur ist wichtig, weil ja mit einem einzigen CGI Script das Formular gezeigt und die Eingaben verarbeitet werden sollen. Mit ähnlichen Kontrollstrukturen lassen sich später auch kompliziertere Aufgaben lösen, beispielsweise die Verarbeitung unterschiedlicher Formulare oder unterschiedlicher Submit Buttons in einem einzigen CGI!
Dieser Teil der Strukturierung ist entscheidend für das sichere Funktionieren eines CGI's und der Hauptteil des Programmierens eines CGI's überhaupt. Natürlich können die Unterfunktionen noch einiges an Arbeitsaufwand erfordern, aber im Wesentlichen ist das Script an dieser Stelle hier schon fertig.
Unterfunktionen schreiben
#---Subfunctions---#
# Datei anlegen und Einträge in Datei schreiben
sub write_file{
my $zeit = localtime(time);
open FH, ">>$ben_dat" or CgiDie("Fehler beim Anlegen oder Schreiben der Benutzerdatei","$!");
print FH "$zeit;$in{'name'};$in{'sex'};$in{'alter'}\n";
close FH;
}
# erfolgreiche Eingaben im Browser anzeigen
sub quit{
my $zeit = localtime(time);
print<<QUIT;
<h3>Benutzereingaben erfolgreich gespeichert!</h3>
<pre>
Datum und Zeit: $zeit
Name: $in{'name'}
Geschlecht: $in{'sex'}
Alter: $in{'alter'}
</pre>
QUIT
}
# Eingaben prüfen
sub einprf{
if( !$in{'name'} or !$in{'alter'} or $in{'alter'} =~ /[^0-9]/ ){
CgiDie("Fehlerhafte Eingabe","Backbutton klicken und Eingabe wiederholen, Name, Geschlecht und Alter muss angegeben werden. Das Alter bitte als einen ganzzahligen Wert eingeben.");
}
}
# Formular aufbauen
sub form{
print<<FORM;
<h3>CGI 4 Beginner, Benutzereingaben in Datei speichern</h3>
<pre>
<form action="$ENV{SCRIPT_NAME}" method="post">
Bitte Füllen Sie alle Eingabefelder aus
Name: <input type="Text" name="name" size="45" >
Geschlecht männlich: <input type="Radio" name="sex" value="Maennlich" checked> Weiblich: <input type="Radio" name="sex" value="Weiblich">
Alter: <input type="Text" name="alter" size="3" maxlength="3">
<input type="Submit" name="ok" value="Eingaben speichern"><input type="reset" value="Eingaben verwerfen">
</form>
</pre>
FORM
}
# Seite aufbauen bis zum Body
sub a_html{
print<<AHTML;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>CGI 4 Beginner</TITLE>
</HEAD>
<BODY>
AHTML
}
# Seite schließen
sub z_html{
print<<ZHTML;
</BODY>
</HTML>
ZHTML
}
|
Erläuterungen zu den Unterfunktionen
Die Funktion write_file weist keine Besonderheiten auf und ist auch für den Anfänger durchschaubar. Wichtig ist es immer beim Anwenden der Funktion open den Rückgabewert abzufragen ob es einen Fehler gab, hilfreich dazu ist die Variable $!. Im vorliegenden Fall wird das Script bei einem Fehler bei open FH,... abgebrochen.
In den Funktionen a_html, z_html, form wird die gesamte Ausgabe per Here is... Konstrukt auf den print Befehl umgeleitet - mit einem einzigen print Befehl wird ein komplettes Dokument an den Browser geschickt. Von Vorteil ist dabei die Möglichkeit einer vereinfachten Schreibweise, so müssen z.B. eingefügte " " nicht maskiert werden.
Interessant ist vielleicht auch die Notifikation form action="$ENV{SCRIPT_NAME}" im einleitenden Form Tag, damit wird dieses CGI vom Namen des Scripts unhängig (falls der Script Name irgendwann mal geändert werden sollte).
Die Funktion einprf prüft in einer oder Verknüpfung ob die Eingabefelder ausgefüllt wurden. Recht einfach wird hier auch geprüft ob das Alter auch wirklich nur Ziffern enthält. Bei fehlerhafter Eingabe wird die weitere Verarbeitung des CGI's abgebrochen mit der Funktion CgiDie und einer selbst definierten Fehlermeldung im Argument dieser Funktion.
CGI auf Webserver installieren
Sofern lokal alles funktioniert kommt der große Moment des
Ausprobierens, seitens des Providers steht ein cgi-bin zur
Verfügung und dort soll natürlich auch dieses Script
installiert werden und laufen. Also stellen wir die Verbindung zum
Provider her über Modem oder ISDN und starten mit unseren
FTP-Zugangsdaten ein geeignetes
FTP Programm.
Ist das Script im ASCII Mode hochgeladen muss es auf dem Server auf
ausführen gesetzt werden, viele Provider reden dabei von
chmod 755 file ... aber auch das
ist zu schaffen!
Eine Besonderheit gibt es jedoch auch bei diesem Script zu beachten:
Es soll eine Datei angelegt bzw. mit Benutzereingaben gefüllt
werden, was heißt das? Nun, je nach Providervorgaben läuft
ein CGI unter einem bestimmten Benutzer Account, das ist meistens die
Gruppe (seltener "Alle"). Soll mit einem solchen CGI also eine Datei
in einem bestimmten Verzeichnis angelegt werden, muss für die
Gruppe auf dieses Verzeichnis ein Schreibrecht bestehen! Die
Vergabe des Schreibrechtes auf ein ganzes Verzeichnis kann umgangen
werden wenn es die Datei bereits gibt, in diesem Fall muss das
Schreibrecht (chmod 666 datei) lediglich auf die Datei gesetzt werden.
Siehe auch: UNIX Dateirechte
Ausblick
Dieser Artikel zeigt wie mit einem guten Lösungsansatz eine
bestimmte Aufgabenstellung als CGI gelöst werden kann. Mit
dem gezielten Einsatz von Modulen oder Libraries (hier cgi-lib.pl)
kann ein Script wesentlich vereinfacht werden und der Programmierer kann
sich auf das Wesentliche beschränken. Strukturierte Programmierung
konsequent angewandt heißt: Übersicht behalten über den
gesamten Ablauf eines Scripts. Hilfreich sind in jedem Falle Kommentare -
so wird ein etwaiger Umzug auf eine andere Plattform oder die Programmpflege
schlechthin vereinfacht.
Das Problem File Locking ist im aufgezeigten Beispiel nicht
berücksichtigt, sollte jedoch in jedem Falle Beachtung finden.
Unter LINUX/UNIX kann dazu die Funktion flock() verwendet werden,
für anderen Plattformen gibt es dazu auch andere Lösungen
wie z.B. das Verfahren der Umbenennung, so wird erreicht, dass eine
Datei tatsächlich nur von einem Prozess beschrieben werden kann.
Um stets die Übersichtlichkeit zu wahren gibt es auch die Möglichkeit,
Unterfunktionen in externe Dateien auszulagern. Siehe dazu auch die
entsprechenden Abschnitte im
Perl Tutorial von Eike Grote
wie Code von externen Dateien eingebunden wird. Tipp: die Funktionen
&a_html und &z_html in eine eigene Library auslagern
und im Argument zum Beispiel übergeben ("Titel","CSS Datei","Hintergrund")...
externe Dateien einzubinden macht i.d.R. immer dann einen Sinn, wenn diese
nur einmal pro Prozess aufgerufen werden, also zum Beispiel im Falle des
Seitenaufbaues beim Aufruf des CGI's.
|