Anmerkungen zu "CGI leicht gemacht!"
CGI-Beispiel-Programme
Wie gewünscht findest Du hier ein paar "Hello World" CGI-Programme um den Anfang leichter zu machen. Die erste Version zeigt nur CGI-Ausgaben, die längere Version gibt den an sie übermittelten Text als HTML einfach wieder aus. Es gibt jeweils eine C und eine Perl-Version.
- Das Nur-Ausgabe-Skript:
-
Das Echoskript, mit zwei Eingabefeldern aufgerufen. Beobachte mal die URL-Zeile in Deinem Browser, wenn Du dieses Skript benutzt.
CGI Mailer Skript
Eines der häufigsten Anwendungsfelder für CGI-Skripts ist es, Formulardaten an eine eMail-Adresse zu versenden. Hier findest Du ein einfaches Skript, daß genau das tut - natürlich in Perl: mailer.pl
Zwei Dinge mußt Du vor der Benutzung aber noch tun, sonst wärs zu einfach:
- Der Pfad in der ersten Zeile des Programms muß dem der Perlinstallation auf dem Server entsprechen. (Evtl. Admin fragen - unter X "which perl" eingeben)
- Die beiden Variablen $mailprog und $recipient sollten das Mailprogramm auf dem Server und Deine eMail-Adresse beinhalten
...Sicherlich ist auch noch überzeugenderer HTML-Output möglich.
g von Form-Daten ohne CGI
Es gibt noch einen Billig-Weg, Form-Daten per eMail zu verschicken, der nur auf HTML basiert. Im FORM Tag mußt Du ACTION auf "mailto:" setzen, und das ENCTYPE -Attribut muß "text/plain" sein. Die meisten Browser können damit umgehen und senden die Form-Daten an die angegebene Adresse. Zum Beispiel:
FORM ACTION="mailto:me@myhost.de" ENCTYPE="text/plain">
Da gibts aber auch Nachteile: Man hat keine Kontrolle über das Format des versendeten Textes und außerdem bekommt der User kein Feedback. Außerdem unterstützen halt nicht alle Browser diese Variante des FORM-Tags.
Sicherheit und CGI-Skripts
Man muß sich einfach mal klar machen, daß ein CGI-Skript ein Programm ist, daß jeder Mensch dieser Welt auf Deinem Rechner laufen lassen kann. Gerade bei Kommandozeilenorientierten Betriebssystemen (Unix) sollte man ziemlich aufpassen, in seinem Skript keine großen Lücken zu lassen.
Wichtig: Traue keiner User-Eingabe. Zum Beispiel sollte man nie vom User übermittelte Daten direkt als Shell-Command ausführen, ohne die Daten zu prüfen. Hacker riechen solche Löcher! Stell Dir mal vor, Du hättest ein CGI-Skript mit dem der User auf Deinem Rechner "fingern" kann. Ein Perl-Skript könnte so aussehen:
system "finger $username" ;
Wenn der geneigte User nun "james; rm -r /" als Usernamen eingibt, wird daraus
system "finger james; rm -r /" ;
was so viele Dateien wie Möglich löscht. Das ist doch wohl nicht, was Du erwartet hast!? Den Usernamen sollte man in diesem Fall zumindest mit folgendem überprüfen:
$username!~/[^\w.-]/ || die "Boa! Netter Versuch...";
Es ist für einen Hacker ja ganz einfach, irgendwelche FORM-Variablen an Dein Skript zu schicken - mit irgendwelchen Werten (auch Steuerzeichen). Dein Skript sollte auf solche Daten nicht reagieren.
Das Skript auf den Server bekommen
Jeder Webserver ist anders konfiguriert. Einige erlauben es, CGI-Skripts ins gleiche Verzeichnis wie die Websites zu packen, die Dateinamen müssen dann mit ".cgi" aufhören. Andere wollen die CGI-Skripts in einem speziellen Verzeichnis haben, meist "cgi-bin". Dein Webmaster sollte Dir da weiterhelfen können.
Du mußt Deinem CGI-Skript noch die richtigen Unix-Permissions geben, um es als ausführbar zu kennzeichnen. Unter Unix läuft der Webserver (wie jeder Prozess) unter einem Usernamen. Dein CGI-Skript muß erstens von diesem User ausfürbar und zweitens auch noch lesbar sein. Unter Unix setzt man diese Permissions mit "chmod 750 *.cgi" (oder "chmod 755 *.cgi" - frag den Webmaster)
Wenn das Skript nicht läuft:
-
Perlskripts kann man auf Syntaxfehler überprüfen: "perl -c myscript.cgi".
-
Achte drauf, daß der Pfad zum Perl- (oder Shell-) Interpreter in der ersten Skriptzeile richtig gesetzt ist. Unter Unix kann man den Perlpfad z.B. mit "which perl" herrausfinden.
-
Natürlich muß man kontrollieren, ob die im erzeugten HTML-File aufrufberen Links so gültig sind - egal ob sie relativ oder absolut angegeben sind.
-
Laß das Skript mal von der Kommandozeile aus laufen und beobachte, was passiert. Weit kommt man damit allerdings meistens nicht, weil die Environment-Variablen nicht belegt werden.
cation">
Ein vorhandenes HTML-File als Antwort senden
Wenn die HTML-Antwort Deines Skripts immer die gleiche ist oder Du mit einem von mehreren vorhandenen Files antworten möchtest, könntest Du das "Location"-Antwortprinzip hilfreich finden. Damit kann man den Browser "auf eine andere URL umleiten" (Ist eigentlich für umgezogene Seiten gedacht).
Hier ein Beispiel. Dein Skript sollte generell diese 3 Zeilen ausgeben (dann funktioniert es mit fast allen Browsern)
Status: 302 Found
Location: response.html
URl: <response.html>
- gefolgt von einer Leerzeile. Der Browser des Users wird daraufhin response.html laden, als sei es die Antwort Deines CGI-Skripts. Hier kann man natürlich relative und absolut Adressen angeben.
In diesem Fall erzeugt man keinen "Content-type:" -Header!
Weitere nützliche Environment-Variablen
CGI-Skripts können auf etwa 20 Environment-Variablen zugreifen - solche wie QUERY_STRING und CONTENT-LENGTH. Hier ist die komplette Liste von NCSA.
Ein paar ausgesuchte sind besonders interessant:
REMOTE_HOST
Diese Variable beinhaltet den Namen des Servers, der die Seite aufgerufen hat. Oft ist das nicht sehr Aussagestark - besser aber, als garnichts. Mehr hat man über den Besucher nicht rauszufinden! Wer mehr wissen will, soll den User um das Hinterlassen einer e-Mail-Adresse bitten.
-
REQUEST_METHOD
-
Beinhaltet die Methode, mit der das Skript aufgerufen wurde. Normalerweise "GET" oder "POST".
PATH_INFO
-
Genauere Pfad-Information. So ist es möglich, dem Skript einen Pfad zu übergeben. Der muß dann hinter der URL des CGI-Skripts stehen:
http://www.myhost.com/mypath/myscript.cgi/path/info/here
würde PATH_INFO auf "/path/info/here" setzen.
SERVER_NAME
-
Hostname und IP Deines Webservers.
SERVER_PORT
-
Der benutzte Port des Webservers (zumindest für diesen Request)
SCRIPT_NAME
-
Die lokale URL des ausgeführten Skriptes. In den CGI-Spezifikationen ist unklar, ob ein führender Slash mit übergeben werden soll. Mit der folgenden Perl-Zeile hat man nie einen führenden Slash:
$ENV{'SCRIPT_NAME'}=~ s#^/## ;
e komplette URL des ausgeführten Skriptes wäre in Perl also
VER_NAME'}:$ENV{'SERVER_PORT'}/$ENV{'SCRIPT_NAME'}"
Die komplette URL mit der das Skript aufgerufen worden ist trüge hinten noch PATH-INFO und QUERY_STRING angehängt.
Nochmal: Bei NCSA's complete list findest Du sie alle.
Ein Bild (oder andere Binärdaten) als Antwort ausgeben
Die meisten CGI-Skripts geben HTML-Daten zurück, man kann aber eigentlich zurückgeben, was man möchte. Man sollte nur den richtigen MIME-Type in der "Content-type:"-Zeile stehen haben - natürlich wieder von einer Leerzeile gefolgt. Anschließend können dir rohen Binärdaten folgen. Bei einer HTML-Antwort ist das HTML-Text. Bei Bildern, Audio oder Video sind es Binärdaten. Ein GIF zum Beispiel gibt man so zurück:
Content-type: image/gif
GIF89a&%--- binary contents of GIF file here ---$(......
Dein HTML-File kann ein solches Skript-generiertes Bild zum Beispiel wie folgt aufrufen:
IMG SRC="gifmaker.cgi?param1=wert1¶m2=wert2"
Eins meiner Lieblingsbeispiele hierfür ist der interaktive Grafikrenderer, der 3D-Icons mit den Farben, Formen, Texturen, Lichtern usw. erzeugt, die ich definiere. Die entstandenen Icons kann man dann auf seiner Seite als Aufzählungspunkt oder HR benutzen. Anm.: Die Seite ist leider down - ich finde auch keinen Mirror mehr...
MIME-Types
MIME-Types sind standardisierte, Casesensitive Strings die einen Dateityp identifizieren. Sie beginnen mit dem generellen Typ der Datei (text, image, audio), gefolgt von einem Slash, um mit dem spezifischen Dateityp (html, gif, jpeg) aufzuhören. HTML-Files sind zum Beispiel als text/html identifiziert, GIFs oder JPEGs heißen jeweils image/gif bzw. image/jpeg.
Der Unterschied zwischen GET und POST
GET und POST sind zwei zwei unterschiedliche Methoden, die im HTTP festgelegt sind. Sie tun recht verschiedene Dinge, sind aber beide geeignet, um Form-Daten zurück an den Server zu senden.
Normalerweise benutzt man GET um eine Datei oder so anzufordern, vielleicht mit ein paar Parametern versehen, die diese genauer beschreiben. Die Daten werden dabei komplett in der URL übertragen:
-
http://myhost.com/mypath/myscript.cgi?name1=wert1&name2=wert2
Dabei dürfen nicht zu viele Daten übertragen werden müssen - die Maximallänge der URL variiert von Browser zu Browser.
POST wird normalerweise dafür verwendet, dem Server einen großen Haufen Daten zum verarbeiten zu übermitteln. (Der Name POST kommt ursprünglich von der Idee, einen Beitrag in eine Newsgroup zu senden) Wenn eine HTML-Form per POST übermittelt wird, werden die Daten auf STDIN zur Verfügung gestellt. Mit POST kann der User zum Beispiel ganze Dateien an den Server uploaden: Die Menge der übertragenen Daten ist im Gegensatz zu GET nicht begrenzt.
All das geschieht hinter den Kulissen. Für den CGI-Programmierer funktionieren GET und POST fast gleich und sind gleich einfach zu benutzen. Der Vorteil von POST ist, daß man beliebig viele Daten übertragen kann. Der Vorteil von GET ist, daß alle Daten in eine URL gebastelt sind - man kann auf sie also verweisen oder sie Bookmarken. (Mit dem AutoPOST-Utility geht das auch per POST)
Welches ist die geeignetste Sprache, um CGIs zu schreiben?
| tr> |