Deutsch English
Home
About tdbengine
Newsletter
Download
Helpware
Forum
Chat
Documentation
Basic Course
Basics
Programmierumgebung
CGI Aufbereitung
EASY Programmierung
Standard-Bibliothek
Die Datenbank
HTML-Formulare
Function reference
HOWTO...?
Projects
Links
Benchmarks
Bug Reporting
Support request
 
Home    Overview    Search    Impressum    Contact    Members
Lesson 3: Die Aufbereitung der CGI-Informationen mit der tdbengine

Nachdem wir in der ersten Lektion Grundsätzliches über die CGI-Schnittstelle erfahren und in der zweiten Lektion die Programmierumgebung der tdbengine kennengelernt haben, geht es diesmal darum, wie die tdbengine die Browser-Informationen aufbereitet und diese schließlich dem Programmierer zur Verfügung stellt

Die automatische Aufbereitung
In EASY gibt es die Funktion GetEnv(), um den Wert von Environment-Variablen zu bestimmen. Und es gibt die Funktion read(0,..) bzw. readln(0), um Daten aus der Standardeingabe zu lesen. Damit ist im Prinzip der komplette Zugriff auf die Informationen den Klienten möglich. Wie aber schon in der ersten Lektion bemerkt, ist ein derartiger Zugriff höchst unkomfortabel.

Um es dem Programmierer möglichst einfach zu machen, führt die tdbengine bei jedem Start folgende Aktionen aus:

Über die Environment-Variable »CONTENT_LENGTH« wir die Anzahl der gültigen Zeichen in der Standardeingabe bestimmt. Dann werden alle Informationen aus der Standardeingabe gelesen und in eine (programm-)interne Speicherstruktur übertragen. Bei dieser Speicherstruktur handelt es sich um einen geordneten Baum. Die Ordnungsstruktur wird aus den Namen der CGI-Variablen gewonnen. Dadurch können die zu einer beliebigen CGI-Variablen gehörenden Informationen dem Programm extrem schnell zur Verfügung gestellt werden.

Mehrere gleichnamige CGI-Variablen führen auch zu mehreren Knoten im Baum, wobei diese jedoch automatisch numeriert werden.

Beispiel:

In der Standardeingabe steht folgende Zeichenkette

Name=Huber&Vorname=Hans&Vorname=Dieter&Beruf=Lehrer&Vorname=Albert...

So wird daraus folgender Baum aufgebaut

Name (Huber)


Beruf (Lehrer)
Vorname (Hans)




Vorname.1 (Dieter)




Vorname.2 (Albert)

Hat beim Lesen und Aufbereiten der Standardeingabe eine Variable einen Namen, der mit »text:« beginnt, so wird zusätzlich ein »ramtext« mit dem Namen der CGI-Variablen angelegt und der Inhalt der CGI-Variablen in diesen internen Speicherbereich kopiert. Der Hintergrund für diese Vorgehensweisen liegt in der Beschränkung von einfachen Zeichenketten auf 255 Zeichen. Ramtexte können wesentlich größere Textbausteine (bis 64 kByte) speichern.

Nach dem Lesen der Standardeingabe erfolgt die Bearbeitung der Environment-Variable »QUERY_STRING« nach ganz ähnlichen Regeln, so dass in der Folge auf die einzelnen Komponenten davon direkt über den jeweiligen Namen zugegriffen werden kann.

Schließlich wird auch noch die Environment-Variable »HTTP_COOKIE« aufbereitet. Die einzelnen Komponenten daraus werden in dem oben angeführten Baum aufgenommen, nur dass hier jedem Namen das Präfix »Cookie.« vorangestellt wird.

Wir wollen hier noch einmal kurz zusammenfassen: Die Informationen der Standardeingabe (also alle mit der Methode »post« übermittelten Daten) und der Inhalt der Environment-Variablen »HTTP_COOKIE« werden in einer (sehr effizienten) internen Baumstruktur aufbereitet. Auch die Informationen der Environment-Variaben »QUERY_STRING« (also die über die Methode »get« übermittelten Daten) werden so aufbereitet, dass das Programm über den Namen der jeweiligen CGI-Variable zugreifen kann.

CGI-Funktionen in EASY
Obwohl erst in der nächsten Lektion ein Crash-Kurs »EASY-Programmierung« folgt, wollen wir bereits in dieser Folge die Basis-Funktionen zur CGI-Programmierung kennenlernen und damit eine Reihe von Experimenten durchführen.

Ein EASY-Programm hat immer eine Prozedur mit dem Namen »Main« (Groß/Kleinschreibung beachten), die beim Start des Programms ausgeführt wird.

Hinweis: Eine Prozedur in EASY entspricht exakt dem, was in den Programmiersprachen Pascal und Modula unter einer Prozedur verstanden wird: eine Funktion ohne Rückgabewert. In der Programmiersprache C entspricht das demnach dem Typ »void«, in Perl (und BASIC) »sub«. Funktionen mit Rückgabewert heissen in EASY »Funktionsprozeduren«.

Innerhalb einer Prozedur stehen »Anweisungen«. Innerhalb einer Zeile werden mehrere Anweisungen durch ein Semikolon getrennt. Eine Prozedur benötigt immer einen Prozedurkopf, hier bekommt sie ihren Namen und eventuell eine Parameterliste. Der Prozedurfuß besteht immer aus dem Wort »ENDPROC«.

Betrachten wir unter diesem Aspekt nochmal das Testprogramm »test.mod«:

PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWriteLn('hello world')
ENDPROC

Zwischen dem Prozedurkopf (PROCEDURE Main) und dem Prozedurfuß (ENDPROC) stehen mehrere Anweisungen der Form cgiwriteln(...). Bei diesen Anweisungen handelt es sich um Aufrufe der Funktion cgiwriteln(). Da diese Funktion bereits fest eingebaut ist (und nicht selbst geschrieben werden muß) und damit also standardmäßig in EASY vorhanden ist, nennt man ein solche Funktion auch Standardfunktion.

Die Standardfunktion cgiwriteln() hat immer ein Argument, nämlich eine Zeichenkette bzw. einen beliebigen Ausdruck, der eine Zeichenkette liefert. Diese Zeichenkette wird an die Standardausgabe geliefert und erscheint damit auf der Konsole, falls das Programm direkt über eine Konsole gestartet wird (Sie erinnern sich: ./bin/tdbengine test.prg) oder eben beim CGI-Klienten, falls es sich um einen CGI-Aufruf handelt.

Anmerkung: Wir wollen in dieser Lektion ausschließlich CGI-Programme testen. Starten Sie also Ihre Programmierumgebung (wie in der letzten Lektion vorgestellt) und verwenden Sie pdk.prg zum Schreiben und Testen der Programme.

Zur Ausgabe von Zeichenketten an die CGI-Schnittstelle stellt tdbengine folgende Funktionen zur Verfügung:

  • cgiwrite(Zeichenkette) gibt die Zeichenkette aus
  • cgiwriteln(Zeichenkette) gibt die Zeichenkette aus plus die Zeichenfolge für Neue Zeile CR/LF
  • cgiwritehtml(Zeichenkette) gibt die Zeichenkette als HTML-Text aus
Während die ersten beiden Funktionen die Zeichenkette unverändert an die Standardausgabe senden, konvertiert die dritte Funktion cgiwritehtml() die Zeichenkette vor der Ausgabe in das HTML-Format. Das betrifft alle Sonderzeichen, zu denen auch die Umlaute und »ß« gehören.

Dazu ein kleines Experiment:

PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWrite('<pre>')
  CGIWriteLn('Das ist ein <b>kleiner</b> Test.')
  CGIWriteHTML('Das ist ein <b>kleiner</b> Test.')
  CGIWriteLn('</pre>')
ENDPROC

Dieses Programm liefert folgende Ausgabe:

Das ist ein kleiner Test.
Das ist ein <b>kleiner</b> Test.

Eine vollständige Tabelle der Übersetzungen aller Zeichen nach HTML sollten Sie in jedem besseren HTML-Buch finden. Sie werden ein solches brauchen, auch wenn Ihnen die tdbengine eine Vielzahl von Konvertierungen abnehmen kann.

Betrachten wir ein weiteres Programm, diesmal mit Umlauten:

PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWrite('<pre>')
  CGIWriteLn('Hüben UND drüben ist es öde UND blöde')
  CGIWriteHTML('Hüben UND drüben ist es öde UND blöde.')
  CGIWriteLn('</pre>')
ENDPROC

Das Programm liefert etwa folgende Ausgabe (kann je nach Betriebssystem und Browser variieren):

H?ben und dr?ben ist es ?de und bl?de
Hüben und drüben ist es öde und blöde.

Ohne Konvertierung können die Umlaute (hier unter Linux/Netscape) überhaupt nicht richtig dargestellt werden. Dazu sollte man wissen, dass die tdbengine derzeit intern (noch) im erweiterten ASCII-Zeichensatz (OEM) arbeitet. Hier werden den nationalen Sonderzeichen andere Codes zugeordnet als im derzeit gebräuchlichen ANSI-Zeichensatz für Deutschland.
Der Grund hierfür liegt weniger im Traditionsbewusstsein der tdbengine-Programmierer, als vielmehr im Mangel wesentlich besserer Alternativen. Alle 8-Bit-Zeichensätze (mit 256 verschiedenen Zeichen) benötigen für Sonderzeichen eine Konvertiertabelle (Codepage), und weil es viel mehr Sonderzeichen als die hier zur Verfügung stehenden 128 gibt (die ersten 128 Zeichen entsprechen in jeder Tabelle dem ASCII-Standard), muss es auch viele Konvertiertabellen geben (für jede Sprachfamilie eine eigene).
Und manche Sprachen haben wesentlich mehr als 128 Sonderzeichen, so dass hier die 8-Bit-Codierung prinzipiell fehlschlägt. Einen Ausweg aus diesem Dilemma bietet ein 16-Bit-Zeichensatz, wie er mit dem »Unicode« zur Verfügung steht. Leider hat auch dieser ein großen Nachteil: Der Speicherbedarf und damit auch das Übertragungsvolumen wird verdoppelt, was jedoch, solange man sich in einem Sprachraum aufhält, absolut überflüssig ist.
Einen anderen, sehr eleganten Ausweg bietet HTML: hier wird jedem Sonderzeichen eine spezielle Zeichenfolge zugeordnet, was zwar den Speicherbdarf für Sonderzeichen erhöht, aber eben nur für diese. Leider ist diese Darstellung in Datenbanksystemen nicht brauchbar. Der Grund hierfür liegt darin, dass in einer solchen Umgebung die Ordnung (Sortierung) von Zeichenketten eine große Rolle spielt.
Und die kann nur dann effizient hergestellt werden, wenn alle Zeichen einer Zeichenkette den gleichen Speicherbedarf haben.

Hinweis: Sie sollten in HTML-Dokumenten grundsätzlich auf alle Sonderzeichen verzichten, selbst wenn diese in Ihrer Codepage/Browser/Betriebssystem-Kombination richtig dargestellt werden sollten. Wird eine Seite in einem anderen Land betrachtet, sieht man nur noch Fragezeichen oder sonstige Hyroglyphen.

Also niemals:

<html>
<body>
<h2>Einführungs-Kurs</h2>
</body>
</html>

Sondern:

<html>
<body>
<h2>Einführungs-Kurs</h2>
</body>
</html>

Eine interessante Randbemerkung: Der erweiterte ASCII-Zeichensatz wird auch auf der Windows-Konsole nachwievor verwendet.

Der Header
Zurück zu unseren Programmbeispielen. Sie werden sich inzwischen sicher fragen, was die ersten beiden Zeilen bedeuten:

CGIWriteLn('content-type: text/html')
CGIWriteLn('')

Versuchen Sie einmal, diesen beiden Zeilen wegzulassen. Beim Ausführen des Programms erhalten Sie sofort eine drastische Fehlermeldung des http-Servers (hier Linux/apache):

Internal Server Error The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, root@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.
More information about this error may be available in the server error log.

Und wenn Sie dem Hinweis folgen und die Fehler-Logdatei des http-Servers konsultieren, erhalten Sie folgenden Hinweis:

[Tue Feb 29 11:39:05 2000] [error] [client 127.0.0.1] malformed header from script. Bad header=hello world ": /home/tdbengine/bin/tdbengine

Hinweis: Die Fehler-Logdatei von apache finden Sie unter /var/log/http.error_log (Linux) bzw. unter /programme/apache group/apache/logs/error.log (Windows und apache-Standard-Installation).

Auch ohne die Dokumentation von apache genau zu kennen, kann man aus der Fehlermeldung erkennen, dass hier ein Fehler im »header« (malformed header) vorliegt.
Offensichtlich muss ein CGI-Programm immer einen solchen Header liefern, der nach ganz bestimmten Regeln gebaut sein muss. Und das wird nach einer kurzen Überlegung auch schnell klar.
Der http-Server nimmt uns (den CGI-Programmierern) eine großen Teil des Dialogs mit dem Klienten (http-Browser) ab. Damit er das kann, müssen wir ihm zunächst mitteilen, was er dem Klienten zu liefern hat. Es ist nämlich keineswegs so, dass ein CGI-Programm ausschließlich HTML-Seiten »ausspuckt«, es können genausogut Bilder oder Töne, PDF-Dokumente oder Videos oder ganz normale »Downloads« sein. In manchen Fällen liefert ein CGI-Programm überhaupt keinen Inhalt, sondern nur einen Verweis auf eine andere Quelle (URL).
Damit also der http-Server dem Klienten mitteilen kann, was nun kommt, benötigt er selbst an allererster Stelle eine entsprechende Information. Und genau diese Funktion erfüllt der Header. Syntaktisch gesehen ist ein Header zunächst einmal eine Reihe von Zeilen, die durch eine Leerzeile abgeschlossen wird. Die abschließende Leerzeile gehört noch zum Header, wird also nicht an den Klienten weitergegeben.

In diesem Einführungs-Kurs verwenden wir ausschließlich den Header, der dem http-Server anzeigt, dass es sich in der Folge um ein HTML-Dokument handelt. Er lautet dann:

content-type: text/html

Erste Programme mit Argumenten via Querystring
Wir wollen wieder ein kleines Begrüßungsprogramm schreiben, das anders als unser (schlampiges) test.mod eine komplette HTML-Seite mit <html> und <body> liefert. Geben Sie folgenden Programmtext ein und benennen Sie das Programm »hallo.mod«.
PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWriteLn('<html><body bgcolor="yellow" text="blue">')
  CGIWriteLn('<h2>')
  CGIWriteLn('Hallo Peter')
  CGIWriteLn('</h2>')
  CGIWriteLn('</body></html>')
ENDPROC

Wenn Sie aber nun nicht gerade »Peter« heissen, werden Sie mit der Begrüßung recht wenig anzufangen wissen. Sie könnten nun im Quelltext statt »Peter« Ihren eigenen Namen schreiben. Interessanter wird die Sache freilich, wenn man das Programm so gestaltet, dass der Name als Parameter in der URL angegeben werden kann:

http://localhost/cgi-tdb/hallo.prg?name=Hans

Wie wir bereits wissen, handelt es sich bei dieser Informationsübermittlung um die Methode »get«, bei der alles, was in der URL nach dem Fragezeichen steht, über die Environment-Variable QUERY_STRING an das CGI-Programm mitgeteilt wird. Und wir wissen weiterhin, dass in EASY auf die Informationen dieser Environment-Variablen über die Funktion GetQueryString() zugegriffen werden kann.

Die Funktion GetQueryString() erhält genau ein Argument, nämlich den Namen der gesuchten CGI-Variablen. Das Funktionsergebnis, also das, was die Funktion liefert, ist wiederum ein Zeichenkette: der Wert der CGI-Variablen.

Für die oben angeführte URL (eigentlich müsste es »der URL« heissen, aber bei der Geschlechtszuweisung von Akronymen, noch dazu, wenn diese aus dem englischen Sprachraum kommen, scheint das Zufallsprinzip zu herrschen) gilt demnach:

getquerystring('name') -> 'Hans'

Hinweis: Zeichenketten(-Konstanten) werden in EASY in einfachen oder doppelten Anführungszeichen angegeben. Wir verwenden hier immer die einfachen Anführungszeichen, ausser diese selbst werden in der Zeichenkette benötigt.

Mit dem bisher gesagten können wir nun ein erstes Programm schreiben, das flexibel auf die Aufruf-URL reagiert:

PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWriteLn('<html><body bgcolor="yellow" text="blue">')
  CGIWriteLn('<h2>')
  CGIWriteLn('Hallo')
  CGIWriteLn(GetQueryString('name'))
  CGIWriteLn('</h2>')
  CGIWriteLn('</body></html>')
ENDPROC

Das Programm wird klaglos seinen Dienst verrichten, solange in der URL kein Umlaut enthalten ist. Geben Sie jedoch einmal folgende URL ein:

http://localhost/cgi-tdb/hallo.prg?name=Rübezahl

Aber auch hier kennen wir schon die Abhilfe: statt CgiWriteLn() verwenden wir CgiWriteHtml(), und schon haben wir das Umlautproblem gelöst:

PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWriteLn('<html><body bgcolor="yellow" text="blue">')
  CGIWriteLn('<h2>')
  CGIWriteLn('Hallo ')
  CGIWriteHTML(GetQueryString('name'))
  CGIWriteLn('</h2>')
  CGIWriteLn('</body></html>')
ENDPROC

Während wir Umlaute auf diese Art und Weise noch relativ einfach in den Griff bekommen, schaut die Sache bei anderen Sonderzeichen ganz anders aus. Schon das Leerzeichen macht größere Probleme:

http://localhost/cgi-tdb/hallo.prg?name=Hans Müller

Hier scheint das Wort »Müller« einfach unter den Tisch zu fallen. Erst wenn wir beispielsweise in einer Internet-Suchmaschine im Feld Suchbegriff mehrere Wörter durch Leezeichen getrennt eingeben und die resultierende URL betrachten, können wir feststellen, dass anstelle des Leerzeichens ein »+«Zeichen erscheint. Geben wird also folgende URL ein:

http://localhost/cgi-tdb/hallo.prg?name=Hans+Müller

Das Ergebnis ist nun wie gewünscht. Was aber, wenn wir das Pluszeichen selbst in der URL übergeben wollen oder müssen. Wieder bringt der Suchmaschinen-Test den Hinweis: Für das Pluszeichen muss die Zeichenfolge »%2B« angegeben werden. Und dieser Hinweis erinnert uns wiederum an die URL-Codierung aus der ersten Lektion dieses Kurses. Dabei wird jedes Sonderzeichen (also jedes Zeichen, das nicht in einer URL stehen darf) durch seinen Codierungswert dargestellt, und zwar als zweistellige hexadezimale Ziffer. Und damit das System weiß, dass es sich um ein derart codiertes Sonderzeichen handelt, wird dieser zweistelligen Hexzahl ein »%«-Zeichen vorangestellt. Eine Ausnahme macht nur das häufig benötigte Leerzeichen, das auch als »+« angegeben werden kann (statt ).

Wenn Sie noch eine Zeichencode-Tabelle (wie sie früher an jeder Programmierer-Wand hingen) zur Hand haben, können Sie die Hexwerte für alle Zeichen direkt ablesen:

A %41
B %42
C %42
...

Sie könnten demnach statt der URL

http://localhost/cgi-tdb/hallo.prg?name=ABC

auch folgende URL verwenden:

http://localhost/cgi-tdb/hallo.prg?name=%41%42%43

Das macht die URL nicht unbedingt lesbarer. Sie müssen zum Glück weder die URL-Codierung in der Informationsübermittlung via URL noch deren Auswertung über die Environment-Variable QUERY_STRING selbst übernehmen. Die Auswertung und Rückübersetzung in den erweiterten ASCII-Zeichensatz übernimmt die tdbengine, und die Codierung erfolgt automatisch durch den http-Browser, wenn wir statt der direkten Angabe in der URL sogenannte Formularfelder verwenden.

Die unmittelbare Angabe von Argumenten in der URL ist jedoch immer dann angebracht, wenn

  • ein CGI-Programm über einen Link aufgerufen wird, oder
  • einem CGI-Programm ein bestimmter Betriebsmodus mitgeteilt wird.
Wir können das recht schön in unserer Entwicklungsumgebung sehen. Wechseln Sie hierzu in das Programm pdk.prg und drücken Sie hier den Schalter »load«. Jetzt wird ein neues Programm mit dm Namen »scanfile.prg« gestartet, das die interaktive Auswahl eines Dateinamen erlaubt. Gehen Sie mit der Maus auf die einzelnen Links und betrachten Sie dabei die Statuszeile Ihres Browsers, in die jeweilige, zum Link gehörende URL angezeigt wird.

Bei den Links, die in ein anderes Verzeichnis verzweigen, sehen Sie beispielsweise:

http://localhost/cgi-tdb/scanfile.prg?filter=install/*.mod&application=/cgi-tdb/pdk.prg&new=1

Es handelt sich hierbei um einen Selbstaufruf des Programms scanfile.prg mit folgenden Argumenten, die das Programm mit der Funktion GetQueryString() auswertet:

filter -> install/*.mod
application -> /cgi-tdb/pdk.prg
new -> 1

Bei der CGI-Variaben »new« handelt es sich um typischen Schalter: Solange hier der Wert »1« angegeben wird, bietet »scanfile« die Eingabe von neuen Verzeichnissen und Dateinamen an. Wechselt der Wert auf »2«, so zeigt das Programm nicht mehr das unter »filter« angegebene Verzeichnis an, sondern gibt ein Formular aus, in dem ein neues Verzeichnis erstellt werden kann. Beim Wert »3« gilt dasselbe, nur dass jetzt ein neuer Dateiname abgefragt wird.

Bei den Links, die direkt zu einem Dateinamen führen, sehen Sie eine URL der Form:

http://localhost/cgi-tdb/pdk.prg?filename=install/dmk.mod

Hier wird also das Programm, das »scanfile.prg« unter der CGI-Variablen »application« übergeben wird, und das es sich bei jedem Selbstaufruf wiederum erneut via URL übergibt, selbst aufgerufen, und das einzige Argument ist die CGI-Variable »filename«, deren Wert der Pfad zu der ausgewählten Datei ist.

filename -> install/dmk.mod

Die Funktion GetQueryString() wird uns im Verlaufe dieses Kurses noch häufig begegnen, so dass wir es an dieser Stelle bei den obigen Ausführungen belassen und uns nunmehr der Datenübermittlung über die Standardeingabe zuwenden können.

Formulare
Bevor wir nun mit Formularen so richtig loslegen können, wollen wir
  • ein Verzeichnis /home/tdbengine/doc einrichten, und
  • dieses Verzeichnis als virtuelles HTML-Verzeichnis »tdbengine« dem http-Server mitteilen
Dazu betrachten wir einerseits die apache und andererseits den Internet Information Server IIS.

Apache

Hier müssen wir einen Eintrag in die Datei http.conf eintragen:

Alias /tdbengine/ /home/tdbengine/doc/

Speichern Sie diese Datei und wechseln Sie auf eine Konsole.

Unter Linux gilt es nun zuerst, den process identifier »pid« für den Basisprozess zu finden. Apache schreibt diesen pid in die Datei httpd.pid. Unter SuSE Linux finden Sie diese Datei im Verzeichnis /var/run/, in vielen anderen Distributionen im Verzeichnis /usr/local/apache/logs/. Mit

cat /var/run/httpd.pid <RETURN>

wird der pid angezeigt, beispielsweise 105

Geben Sie nun auf der Konsole folgenden Befehl ein:

kill -HUP 105 <RETURN>

Das hat zur Folge, dass sämtliche Kind-Prozesse von apache beendet werden, und der Basisprozess die Konfigurationsdateien neu liest und abarbeitet.

Unter Windows (wenn als Konsolen-Applikation gestartet) wechseln Sie ebenfalls auf eine Konsole und geben dort

apache -k restart <RETURN>

ein. Leider funktioniert das erst ab Version 1.3.3. Bei früheren Version müssen Sie die Ausführung von apache mit Strc-C (in der apache-Konsole) abbrechen und dann das Programm erneut starten.

Beim Internet Information Server IIS aktivieren Sie die Administration dieses Dienstes. Selektieren Sie hier den www-Dienst durch einen Doppel-Klick. Unter »Verzeichnisse« tragen Sie das virtuelle Verzeichnis »/tdbengine/« ein, das dem realen Verzeichnis »c:\home\tdbengine\doc« entsprechen soll.

So, nun können Sie im Verzeichnis /home/tdbengine/doc/ beliebige HTML-Dokumente ablegen und mit der URL »http://localhost/tdbengine/xyz.html« darauf zugreifen. Dieser Kurs setzt eigentlich schon ein paar Grundkenntnisse von HTLM voraus. Allerdings reichen wirklich Grundkenntnisse, und das Internet ist genauso voll von Informationen zu diesem Thema wie Zeitschriften, Bücher und Volkshochschulkurse. Nur sollten Sie an dieser Stelle keine speziellen HTML-Editoren verwenden, die unser spezielles Anliegen an dieser Stelle nur erschweren würden.

Öffnen Sie also jetzt einen beliebigen Text-Editor (notepad, textedit etc.) und nicht etwa ein Textsystem wie Word oder Staroffice, und geben Sie dort folgenden Text ein:

<html>
<body bgcolor="white">
  <h2>Ein ersters Formular</h2>
  <form action="/cgi-tdb/hallo.prg" method="post">
    Dein Name: <input type="text" name="name" size="20">
    <input type="submit" value=" ok ">
  </form>
</body>
</html>

Speichern Sie diesen Text (Dokument klänge hier reichlich hochgegriffen) unter dem Namen »formular.html« im Verzeichnis /home/tdbengine/doc/ ab. Öffnen Sie nun wieder Ihren Browser und geben Sie dort die URL »http://localhost/tdbengine/formular.html« ein. Sie erhalten nun ein kleines Eingabeformular mit zwei aktiven Elementen: Ein Eingabefeld und einen Schalter.
Geben Sie nun in diesem Formular Ihren Namen ein und klicken Sie dann auf den ok-Schalter. Wieder wird unser Programm »hallo« gestartet (action = »/cgi-tdb/hallo.prg«), aber leider wird der eingegebene Name nicht ausgegeben. Das ist allerdings auch nicht weiter verwunderlich, denn wir haben im Formular ausdrücklich die Methode »post« gewählt, und das Programm »hallo.prg« holt seine Eingabe aus der Environment-Variable »QUERY_STRING«, benützt also die Methode »get«. Ändern wir also das Programm »hallo« so ab, daß anstelle von GetQueryString() die Funktion CgiGetParam() aufgerufen wird:

PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWriteLn('<html><body bgcolor="yellow" text="blue">')
  CGIWriteLn('<h2>')
  CGIWriteLn('Hallo ')
  CGIWriteHTML(CGIGetParam('name'))
  CGIWriteLn('</h2>')
  CGIWriteLn('</body></html>')
ENDPROC

Vergleich: GetQueryString und CGIGetParam
Die Funktion CgiGetParam() erhält genau wie GetQueryString() als Argument den »Namen« der gesuchten CGI-Variablen. Ebenso ist bei beiden Funktion die Groß/Kleinschreibung des Namens der CGI-Variablen egal. Wir wollen hier die wichtigsten Unterschiede der beiden Funktionen zusammenfassen:
Funktion
getquerystring
cgigetparam
Argument Name der CGI-Variablen Name der CGI-Variaben
Wert Aus der Environment-Variablen QUERY_STRING (also aus dem, was in einer URL dem Fragezeichen folgt) Aus der Standardeingabe
Unterstützung mehrerer Variablen gleichen Namens Nein Ja, mit Name.1, Name.2 ...
Max. Ergebnislänge 255 Zeichen 255 Zeichen bei einfachen Variablen
64 Kbyte bei Textareas

Eingabeelemente in HTML-Formularen
Wir wollen nun zum Abschluss dieser Lektion ein Formular gestalten, das die gebräuchlichsten Eingabeelemente enthält, sowie eine Auswertung des Formulars mit einem CGI-Programm, wobei die Auswertung hier allerdings nur in einer Wiederholung der Eingaben des Anwenders besteht.

Für die Eingabeelemente in HTML-Formularen stehen folgende Tags zur Verfügung:

  • input
  • select
  • textarea
Jedes dieser Tags hat eine Reihe von Parametern. Der wichtigste, den alle drei gleichmaßen haben, ist der Parameter »name«, denn erst damit wird es möglich, über die Funktion CgiGetParam() auf die jeweiligen Eingaben zuzugreifen. Obwohl die Reihenfolge der Parameter innerhalb eines HTML-Tags keine wesentliche Rolle spielt, sollte der Parameter »name« immer ziemlich am Anfang stehen, damit dem CGI-Programmierer der Überblick erleichtert wird.

input-Tag

Die weiteren Parameter bei »input« sind:

type =

  • »text« Texteingabefeld
  • »password« wie »text«, die eingegebenen Zeichen werden jedoch als Sternchen ausgegeben
  • »submit« Schaltfläche zur Beendigung der Eingabe
  • »image« wie »submit«, nur ist hier ein Bild die Schaltfläche
  • »hidden« verstecktes Feld (ohne den Parameter »value« recht sinnlos)
  • »checkbox« Führt zu einer Checkbox (zum Ankreuzen)
  • »radio« Führt zu einem »Radiobotton«


Hinweis 1: »password« bietet ausschließlich einen »Sichtschutz« bei der Eingabe. Die Datenübertragung erfolgt unverschlüsselt, wenn kein SSL-Protokoll eingesetzt wird. Besonders in solchen Fällen, wenn der Wert dieses Feldes (etwa bei Fehleingaben) an den Anwender zurückgeschickt wird, ist er im Klartext (view source) sichtbar!

Hinweis 2: »hidden«-Felder sind eine sehr sinnvolle Einrichtung, denn damit kann ein HTML-Formular einem CGI-Programm »am Anwender vorbei« Informationen zukommen lassen. Starten Sie einmal das bereits bekannte Programm »dmk.prg« und betrachten Sie unter diesem Aspekt den Quelltext in Ihrem Browser. Sie sehen gleich drei dieser versteckten CGI-Variablen: »dbname«, »start« und »session«.

value hier steht bei »text« und »password« der Vorgabewert.

Bei »submit« handet es sich um den Wert, den die CGI-Variable übermittelt, wenn der Anwender den Schalter drückt. Zugleich wird dieser Wert in der Schaltfläche ausgegeben. Bei »image« wird der Wert nicht übermittelt, sondern die Koordinaten des »Klickpunktes« im Bild.

Bei den Typen »checkbox« und »radio« kann mit »value« kein Vorgabwert festglegt werden. Hier ist vielmehr der Parameter »checked« anzugeben, wenn das Feld bereits beim Öffnen des Formulars angekreuzt sein soll. Bei beiden Typen definiert »value« den Wert, den das CGI-Programm für die ausgewählte Alternative erhält.

size legt die Breite des Eingabefeldes fest.

Innerhalb des Eingabefeldes wird der eingegebene Text vertikal gescrollt.

maxlength legt die maximale Zahl der Zeichen fest, die hier eingegeben werden dürfen. Diese Angabe ist dann wichtig, wenn die Daten in eine Tabelle eingetragen werden und die Zeichenzahl begrenzt ist (also praktisch in allen STRING-Feldern). Damit unterbinden Sie von vornherein »abgeschnittene« Datenfelder.

select-Tag

»select« führt zu einer Auswahlliste. Soll dem Anwender die Möglichkeit gegeben werden, mehrere Optionen auszuwählen (statt genau einer), so muss das Tag das Wort »multiple« enthalten. Der optionale Parameter »size« gibt die Anzahl der Zeilen an, die für die Auswahl (sichtbar) zur Verfügung stehen. Sind mehr Optionen vorhanden, als in diesen Zeilen dargestellt werden können, so erscheint ein Scroll-Balken.

Das »select«-Tag macht einen Container auf, der beliebig viele »option«-Tags enthalten kann und mit »</select>« wieder geschlossen wird. Jedes Option-Tag selbst hat einen »value«-Parameter, der den Wert für die Funktion CgiGetParam() festlegt, wenn der Anwender genau diese Option auswählt. Die Vorauswahl wird durch das Wort »selected« ausgedrückt.

textarea-Tag

Damit wird ein Eingabefeld für größere Texte angelegt. Der Name sollte immer mit »text:« beginnen, denn dadurch wird der tdbengine mitgeteilt, dass hier mehr interner Speicherplatz zur Verfügung gestellt werden muss als bei einfachen Zeichenketten (255 Zeichen). Neben m Namen sind noch folgende Parameter wichtig:

rows Anzahl der sichtbaren Zeilen des Eingabefeldes
cols Anzahl der sichtbaren Spalten des Eingabefeldes

Mit »wrap« können Sie festlegen, dass der Text bei der Eingabe innerhalb des Eingabefeldes Umbrochen wird. Fehlt diese Angabe, wird in jeder Richtung gescrollt.

Die Vorgabe einer »textarea« folgt unmittelbar dem Tag und endet erst mit »</textarea>«. Beachten Sie bitte, dass dabei auch Zeilenumbrüche enthalten sind. Steht in Ihrem Formular die Konstruktion

<textarea name=»text:bemerkung«>
</textarea>

so enthält der Text immer eine Leerzeile (mit Zeilenende), auch wenn der Anwender nichts eingibt. Richtig ist hier:

<textarea name=»text:bemerkung«></textarea>

Die Formular-Auswertung
Mit diesen Informationen können wir nun ein recht umfassendes Formular gestalten:
<html>
<body bgcolor="white">
<h2>Ein umfangreiches Formular</h2>
<form action="/cgi-tdb/formulartest.prg" method="post">
<input type="hidden" name="formular" value"standard">
<pre>
  Vorname:    <input type="text" name="vorname" size="30" maxlength="30">
  Name:       <input type="text" name="name" size="30" maxlength="30">
  Passwort:   <input type="password" name="passwort" size="10" maxlength="10">
  Geschlecht: <input type="radio" name="sex" value="w" checked> weiblich
              <input type="radio" name="sex" value="m"> männlich
  angestellt: <input type="checkbox" name="angestellt" value="ja">
  Ausbildung: <select name="ausbildung">
                <option value="hauptschule">Hauptschule
                <option value="realschule">Realschule
                <option value="abitur">Abitur
                <option value="studium">Studium
              </select>
  Bemerkung:  <textarea name="text:bemerkung" rows="10" cols="50" valign="top"></textarea>
  <input type="submit" value=" ok ">
</pre>
</form>
</body>
</html>
Hinweis: Wir haben hier absichtlich keine Tabelle verwendet, um den Blick auf das Wesentliche (die Eingabefelder) zu erhalten.

Was jetzt noch fehlt, ist das Programm »formulartest« zur Auswertung des Formulars:

PROCEDURE Main
  CGIWriteLn('content-type: text/html')
  CGIWriteLn('')
  CGIWriteLn('<html><body>')
  CGIWriteLn('<h2>Auswertung des Formulars</h2>')
  CGIWrite('<pre>')     CGIWrite('Formular: ')
    CGIWriteHTML(CGIGetParam('formular'))
    CGIWriteLn('')     CGIWrite('Vorname: ')
    CGIWriteHTML(CGIGetParam('vorname'))
    CGIWriteLn('')     CGIWrite('Name: ')
    CGIWriteHTML(CGIGetParam('name'))
    CGIWriteLn('')     CGIWrite('Geschlecht: ')
    CGIWriteHTML(CGIGetParam('sex'))
    CGIWriteLn('')     CGIWrite('Ausbildung: ')
    CGIWriteHTML(CGIGetParam('ausbildung'))
    CGIWriteLn('')     CGIWrite('Bemerkung: ')
    CGIWriteHTML(CGIGetParam('text:bemerkung'))
    CGIWriteLn('')   CGIWriteLn('</pre>')
  CGIWriteLn('</body></html>')
ENDPROC

Dieses Programm sieht umständlich aus und ist es auch. Aber es funktioniert, und das ist an dieser Stelle (und beim Programmieren eigentlich immer) das Wichtigste.
Es funktioniert zumindest solange recht gut, bis Sie im Feld »Bemerkung« einen längeren Text eingeben.
Dann werden Sie bemerken, daß hier alles nach dem 255-ten Zeichen abgeschnitten wird.
Aber keine Sorge. Der Inhalt des Feldes ist keineswegs verlorengegangen. Uns fehlen bislang nur die Mittel, um den gespeicherten Text wieder zur Anzeige zu bringen. Aus diesem Grund gibt es in der nächsten Lektion eine Blitzeinführung in EASY, die Programmiersprache der tdbengine. Freilich wird dabei die Mehrzahl der Beispiele aus der »CGI-Ecke« kommen, so daß auch eingefleischte EASY-Programmierer auf ihre Kosten kommen sollten.

Aufgaben:
  1. Warum sollten in HTML-Dokumenten (und damit auch in den Ausgaben von CGI-Programmen) keine nationalen Sonderzeichen verwendet werden?
  2. Welche Funktion hat der »header«, den jedes CGI-Programm vor der eigentlichen Ausgabe schreiben muss?
  3. Erläutern Sie kurz den Unterschied zwischen den Funktionen »getquerystring« und »cgigetparam«.
  4. In unserem Testprogramm »formulartest« haben wir eine übermittelte CGI-Variable vergessen. Um welche handelt es sich. Erweitern Sie das Programm, so dass auch der Wert dieser Variablen ausgegeben wird.
  5. Gestalten Sie Eingabeformular für sämtliche Felder unserer Datenbank »address.dat« aus der zweiten Lektion. Beachten Sie bei den STRING-Feldern die Anzahl der maximal erlaubten Zeichen. Schreiben Sie ein dazugehörendes Auswertung-Programm, das sämtliche Eingaben auf dem Bildschirm (in einer HTML-Seite) wiederholt.
  6. Welche Funktion könnte die versteckte Variable »formular« in unserem umfangreichen Testformular haben?


tdbengine Anwendungen im Web:

Open-Source Web CMS


Open-Source Bug-Tracking


Free wiki hosting

Open-Source Wiki-System

Kostenloses Foren-Hosting

Diät mit tdbengine 8-)

tdbengine chat
irc.tdbengine.org
#tdbengine

   Copyright © 2003-2004 tdb Software Service GmbH
   Alle rechte vorbehalten. / All rights reserved
   Last changed: 04.05.2004
{Fehler für :execmacro{execmacro="sessionspy"}


ranking-charts.de

Programmers Heaven - Where programmers go!