Mit HTML::Mason
entstehen hochperformante
dynamische Webseiten einfach durch in HTML eingebettetes Perl.
Auf dem Netscape-Campus in Mountain View wird nicht nur hart gearbeitet, sondern auch viel Sport getrieben. Es gibt Basketball-Courts, Beach-Volleyballfelder und eine Rollerhockey-Anlage. In den Gebäuden sind Pool-Billiard und Kicker (amerikanisch: ``Foosball'') Standard. Neulich kam in unserer Abteilung eine Tischtennisplatte hinzu und eine neue Sportmodewelle nahm ihren Lauf.
So kam mir die Idee, schnell eine Online-Rangliste zu implementieren. Nach bestimmten Regeln sollten niedriger eingestufte Leute höher rangierende herausfordern, und, falls der Herausforderer gewänne, mit dem Verlierer den Platz in der Rangliste tauschen. Ein CGI sollte es jedem erlauben, Listenplätze zu verändern und neue Mitspieler am Ende der Liste einzufügen.
Da meine künstlerischen Fähigkeiten sich in Grenzen halten, wollte ich mit vorbehalten, vielleicht später die Grafikabteilung um ein nettes Layout zu bitten. Reines CGI kam also nicht in Frage, da die Damen und Herren Künstler mit Perl nichts anzufangen wissen.
Nun gibt es mehrere Möglichkeiten, Perl in HTML einzubetten
und so dynamische Abläufe in Webseiten zu steuern,
Gerald Richters HTML::Embperl
zum Beispiel.
So können Grafiker wie gewohnt HTML-Code editieren, der versteckten
Perl-Code enthält.
Seit neuestem geistert ein neues derartiges System durch die
Gegend: HTML::Mason
.
HTML::Mason
?HTML::Mason
ist ein Perl-Modul von Jonathan Swartz, das einen
mit mod_perl
beschleunigten Apache-Server dazu überredet, sogenannte
Mason-Komponenten zu verarbeiten -- in HTML eingebettetes Perl.
Diese Komponenten dürfen wiederum weitere Komponenten hinzuziehen und Parameter an sie übergeben. Besonders gekennzeichnete Initialisierungsbereiche durchläuft HTML::Mason nur einmal und nicht bei jedem Aufruf, sogenannte Autohandler schnappen sich alle Seiten eines Verzeichnisses -- kurzum, ein äußerst mächtiges System zur Steuerung dynamisch generierter Webseiten.
Statt nun beispielsweise eine statische HTML-Seite zu erzeugen,
deren Submit-Knopf einen in Perl geschriebenen und als CGI
implementieren Formular-Handler aufruft, kann man mit HTML::Mason
Formularerzeugung
und -verarbeitung in einer Komponente verbinden.
Liegen so beispielsweise keine Eingabeparameter vor, stellt die Komponente ein Eingabeformular vor, dessen Submit-Knopf wiederum zurück auf die Komponente zeigt. Füllt der Benutzer die Formularfelder aus, wirft die Komponente den Code zur Formularverarbeitung an und gibt vielleicht eine weitere Komponente als Antwort zurück. Diese Vorgänge spielen sich alle in Perl-erweitertem HTML ab. Intelligentes Caching und ein permanent aktiver Perl-Interpreter beschleunigen die Abarbeitung dieser Komponenten dramatisch, bei Seiten mittlerer Komplexität ist kaum ein Unterschied zu statischen Seiten feststellbar.
Wie soll nun die Pingpongliste funktionieren? Ruft der Benutzer
die Seite pingpong.html
auf, kommt die aktuelle Tabelle nach Abbildung
1 hoch.
Abbildung 1: Die Hauptseite zur Anzeige der Liste. |
Klickt man auf den Knopf ``Edit Table'', erscheint, wie in Abbildung 2 dargestellt, eine Eingabemaske zur Manipulation der Tabelle. Jeder Tabellenplatz ist mit einer Checkbox hinterlegt. Wählt der Benutzer so zwei Plätze an und drückt den Knopf ``Switch Selected Entries'', tauscht die Komponente beide Plätze und gibt wiederum die editierbare Tabelle zurück. Füllt der Benutzer andererseits die Eingabebox weiter unten mit einem neuen Spielernamen und drückt den Knopf ``Add Name'', fügt die Komponente den neuen Namen unten in die Tabelle ein. Ein Mausklick auf den Knopf ``Back to List'' hingegen lässt die Komponente wieder zurück zur ursprünglichen Anzeige nach Abbildung 1 springen, die selbstverständlich auch die durchgeführten Änderungen reflektiert.
Abbildung 2: Die Seite zum Editieren der Liste. |
Die Logik dieser drei Komponenten steht in den Listings
pingpong.html
, display.html
und edit.html
.
Listing pingpong.html
zeigt die Hauptkomponente, die die
Logik des Ablaufs implementiert. Die mit
<%args>...</%args>
ausgezeichnete erste Sektion in pingpong.html
definiert
die Parameter, die die Komponente entgegennimmt.
Ruft der Webserver die Komponente auf, stehen dort die vom Benutzer
nach der GET oder der POST-Methode gesetzten CGI-Parameter zur Verfügung.
Voraussetzung hierfür ist allerdings, dass in der
<%args>
-Sektion eine gleichnamige Variable definiert wurde.
Nach einem =>
-Pfeil steht dort neben jedem Parameter auch noch
ein Default-Wert, auf den die Variable gesetzt wird, falls kein
entsprechender Eingabeparameter vorliegt.
Ruft also beispielsweise ein Browser den URL
http://server/mason/\ pingpong.html?edit=1
auf, erhält der CGI-Parameter edit
nach der GET-Methode den Wert
1
und HTML::Mason
setzt wegen der ersten Zeile der
<%args>
-Sektion den Wert der Variablen $edit
auf 1.
Verlangt der Browser hingegen schlicht nach
http://server/mason/pingpong.html
ist die CGI-Variable edit
nicht gesetzt und dementsprechend
steht $edit
für den Rest der Komponente auf dem in
der <%args>
-Sektion gesetzten Defaultwert 0
.
HTML::Mason
bettet Perl auf verschiedene Arten in HTML ein:
<%...%>
stehender Perl-Code wird ausgeführt
und der Ausdruck durch das Ergebnis des Perl-Codes ersetzt
(<% $edit %>
liefert beispielsweise den Wert der Variablen
$edit
ins HTML der Seite zurück).
<%perl>...</%perl>
stehender Perl-Code
wird bei jedem Aufruf der Komponente ausgeführt und der Rückgabewert
ignoriert.
<%once>...</%once>
stehender Perl-Code
wird genau einmal ausgeführt, wenn nämlich der Apache die Komponente
lädt -- und
dann nie wieder, obwohl alles weiterhin im Speicher residiert. So bleiben
etwa definierte Konstantenwerte oder Funktionen erhalten.
<%perl>...</%perl>
einzubetten,
kann man auch an den Anfang (ohne Leerzeichen!)
jeder Perl-Zeile ein %
-Zeichen schreiben.
01 <%args> 02 $edit => 0 03 $view => 0 04 $switch => 0 05 $userlist => [] 06 </%args> 07 08 <HTML> 09 10 <HEAD> <TITLE> <% $TITLE %> </TITLE> </HEAD> 11 <BODY BGCOLOR="<% $BGCOLOR %>"> 12 13 <CENTER> 14 15 <H1><FONT FACE=ARIAL> <% $TITLE %> </FONT></H1> 16 17 <%perl> 18 my @users = users_read(); 19 if($edit and !$view) { 20 $m->comp("/edit.html", 21 users => \@users, %ARGS); 22 } else { 23 $m->comp("/display.html", users => \@users); 24 } 25 close DATA; 26 </%perl> 27 28 </CENTER> 29 </BODY> 30 </HTML> 31 32 <%once> 33 my $BGCOLOR = "#ddddff"; 34 my $TITLE = 'Ping Pong Ranking List'; 35 my $DATA_FILE = '/home/mschilli/DEV/ix/68/eg/tt.dat'; 36 37 ################################################## 38 sub users_read { 39 ################################################## 40 41 use Fcntl qw(:DEFAULT :flock); 42 43 # Read in data file 44 sysopen(DATA, $DATA_FILE, O_RDWR | O_CREAT) or 45 die "Cannot open $DATA_FILE: $!"; 46 47 # Lock it. Move back to beginning 48 flock(DATA, LOCK_EX); 49 seek(DATA, 0, 0); 50 51 # Read out existing records 52 my @users = <DATA>; 53 54 return @users; 55 } 56 </%once>
Zeile 10 in pingpong.html
übernimmt beispielsweise den
Wert einer Variablen $TITLE
nach Strategie (1) in den HTML-Code.
$TITLE
selbst wurde nach Strategie (3) in Zeile 34 festgesetzt.
Da <%once>
-Sektionen
vor allen anderen ausgeführt werden, ist dies zulässig. So
wird aus
<HEAD> <TITLE> <% $TITLE %> </TITLE> </HEAD>
schnell
<HEAD> <TITLE> Ping Pong Ranking List </TITLE> </HEAD>
Übrigens gelten überall in HTML::Mason
die strengen
Anforderungen von use strict
-- keine undeklarierten Variablen,
weiche Referenzen oder Barewords sind erlaubt.
Die <%once>
-Sektion ab Zeile 32 in pingpong.html
definiert außer einigen Variablen auch noch eine Funktion
users_read()
, die unsere Tabellendatei ausliest. Deren Format
ist einfach ein Spieler pro Zeile und nachdem alle Zeilen in
@users
eingelesen wurden, gibt users_read()
dessen Elemente als
Liste zurück.
Findet pingpong.html
die Datei nicht vor, legt sie eine neue an.
Dieser Luxus erfordert überlegtes Handeln, um das Programm
gegen sogenannte Race-Conditions zu schützen: Mit einem normalen
Dateitest, einem anschließenden open
und nachfolgendem flock
wäre es nicht getan. Da der Webserver Anfragen quasi gleichzeitig
abarbeitet, könnten sich verschiedene Instanzen des Skripts
zwischen den Einzelanweisungen gegenseitig in die Quere kommen
und Datensalat erzeugen.
Die Logik zwischen den Zeilen 44 und 49 ist hingegen narrensicher:
Der sysopen
-Befehl kann eine Datei gleichzeitig zum Lesen und Schreiben
öffnen und sie auch noch erzeugen, falls sie noch nicht
existiert -- und das ganze atomar, also ohne dass jemand
dazwischenfunken kann. Das normale open
könnte das nicht.
Die Konstanten O_RDWR
und O_CREAT
definiert das Modul Fcntl
,
das Zeile 41 hereinzieht. Zeile 48 setzt einen exklusiven Lock auf
die Datei und 49 fährt zurück zum Anfang, falls jemand mit der
Datei jongliert hat, bevor der Lock den Daumen draufhielt.
Aufgabe von pingpong.html
ist es, die aktuelle Spieler-Datei
einzulesen (Zeile 18) und anschließend zur Anzeigekomponente
display.html
oder zur Editierkomponente edit.html
zu
verzweigen, je nachdem, ob die CGI-Parameter edit
oder
view
gesetzt sind.
Am Ende schließt pingpong.html
in Zeile 25 die mit DATA
verknüpfte
Datei wieder. Dieses Datei-Handle nutzt die aufgerufene Komponente
edit.html
weiter unten, um eventuell Manipulationen an der
Datei und damit der persistenten Tabelle vorzunehmen.
In Perl-Sektionen erfolgt der Aufruf anderer Komponenten über
die comp
-Methode des Mason-Objekts, dessen Referenz immer
in $m
vorliegt. Bekommt die Komponente außerdem auch noch
eine Reihe von Parametern mit, werden diese einfach als Name/Value-Paare
angehängt:
$m->comp("/edit.html", "users" => \@users, %ARGS);
ruft edit.html
auf und gibt unter dem Parameternamen users
eine Referenz auf den @users
-Array mit. Ausserdem soll auch
edit.html
alle Eingangs-Parameter von pingpong.html
mitbekommen
-- im Spezial-Hash %ARGS
sind alle versammelt. Auch außerhalb
einer Perl-Sektion kann eine Mason-Komponente übrigens eine
Unterkomponente aufrufen:
<& /edit.html, users => \@users, %ARGS &>
lautet die Syntax für den oben beschriebenen Aufruf aus regulärem HTML heraus.
Listing display.html
zeigt die Komponente, die pingpong.html
aufruft, falls die Spielertabelle erscheinen soll. Als Parameter
übergibt pingpong.html
eine Referenz auf die Spielerliste
@users
, die display.html
in der Argumentsektion entgegennimmt.
Listen an Komponenten zu übergeben funktioniert in Mason übrigens nicht nur mit Aufrufen an Unterkomponenten -- auch CGI-Parameter können nicht nur als Einzelwerte, sondern auch als Listen daherkommen. Dies ist der Fall, falls der Browser einen Eingabeparameter mehrfach setzt:
http://server/mason/\ pingpong.html?p=1&p=2
Hier stehen in Mason etwa nach
<%args> $p => [] @p => () </%args>
in @p
die Werte (1,2)
und $p
enthält [1,2]
. Mit
[]
(Referenz auf leere Liste) und ()
(leere Liste) führen
die Variablen auch dann sinnvolle Werte, falls die Übergabe
nicht klappt. Ohne Defaultwerte besteht Mason auf den Parametern
und löst einen Fehler aus, falls der Browser sie nicht liefert.
Abbildung 3 zeigt, was passiert, wenn der Browser display.html
testhalber
mit folgendem URL aufruft:
http://localhost/mason/display.html\ ?users=Hugo&users=Bernie
Ruckzuck steht dann $users
auf ["Hugo", "Bernie"]
und
display.html
formt eine Tabelle daraus.
Abbildung 3: display.html testhalber aufgerufen |
Die wechselnden Farben in den Tabellenzeilen nach Abbildung 1 erzeugt
display.html
über den in Zeile 6 definierten Array @COLORS
,
in den Zeile 13 mit einem alternierenden Index $i
hineingreift.
Zwischen den Zeilen 11 und 22 befindet sich eine foreach
-Schleife,
die als Körper sowohl Perl-Code als auch reguläres HTML mit
wiederum eingebautem Perl-Code enthält -- Alltag in Mason.
01 <%args> 02 $users => [] 03 </%args> 04 05 <%perl> 06 my @COLORS = ("#eeeeff", "#ffffff"); 07 my $i = 0; 08 </%perl> 09 10 <TABLE> 11 % foreach my $user (@$users) { 12 % $i++; 13 % my $color = $COLORS[$i % 2]; 14 15 <TR BGCOLOR="<% $color %>"> 16 <TD> <FONT FACE=ARIAL SIZE=+2> 17 <B> <% $i %>. </B> </FONT> 18 <TD> <FONT FACE=ARIAL SIZE=+2> 19 <B> <% $user %> </B> </FONT> 20 </TR> 21 22 % } 23 </TABLE> 24 25 <FORM METHOD="POST"> 26 <FONT FACE=ARIAL> 27 <INPUT TYPE=SUBMIT NAME=edit VALUE="Edit Table"> 28 </FONT> 29 </FORM>
display.html
zeigt ab Zeile 25 ein Formular, dessen Submit-Knopf zur
editierbaren Version der Tabelle verzweigt.
Das FORM-Tag setzt als METHOD-Attribut POST
, gibt aber keine
ACTION
an -- also wird der Browser nach dem
Drücken des Submit-Knopfes nach pingpong.html
zurückspringen
und dort die CGI-Variable edit
nach der POST-Methode auf 1 setzen.
Übrigens erscheint der URL zu display.html
bei
aktivem pingpong.html
niemals im Browser
-- es handelt
sich lediglich um eine Komponente, die pingpong.html
bei Bedarf
ansaugt.
Listing edit.html
zeigt die Komponente, die das editierbare
Formular ausgibt. Sie erhält als Parameter nicht nur eine Referenz
auf den Spielerarray ($user
), sondern auch die Werte von $switch
und $new
, die anzeigen, ob der Benutzer bei einem vorhergehenden
Aufruf von edit.html
Spielerränge vertauschen oder neue
Spieler einfügen wollte.
Im ersten Fall steht in $switchlist
eine Referenz auf einen
Array, der die beiden Indexpositionen der zu vertauschenden
Tabellenplätze enthält. Im zweiten Fall steht in $newname
der
Name des einzufügenden Spielers. Die Werte dieser Parameter steuert
das weiter unten definierte HTML-Formular. Die verschiedenen
Submit-Knöpfe setzen die Parameter $new
bzw. $switch
.
Der Perl-Code zwischen den Zeilen 12 und 31 manipuliert das Array,
auf das $users
zeigt und schreibt es zurück in die noch
mit DATA
geöffnete Tabellendatei. Hierzu fährt seek
an den Dateianfang zurück, dann löscht truncate
den
bestehenden Inhalt und print
schreibt neue Daten hinein.
Warum der Aufwand?
Auf DATA
steht noch ein flock
, um bei parallelen Zugriffen
keinen Datensalat zu generieren. Um den flock
zu behalten,
darf mit DATA
zwischen dem Lesen und Wieder-Beschreiben kein
close()
erfolgen.
01 <%args> 02 $users => [] 03 $switch => 0 04 $switchlist => [] 05 $new => "" 06 $newname => "" 07 </%args> 08 09 <FORM METHOD="POST"> 10 <INPUT TYPE=HIDDEN NAME=edit VALUE=1> 11 12 <%perl> 13 ################################################## 14 # Data manipulation 15 ################################################## 16 # Switch ranks if requested 17 if($switch) { 18 my($from, $to) = @$switchlist; 19 ($users->[$from], $users->[$to]) = 20 ($users->[$to], $users->[$from]); 21 } 22 # Add new user if requested 23 if($new) { 24 push(@$users, $newname); 25 } 26 # Daten zurückschreiben 27 seek DATA, 0, 0; 28 truncate DATA, 0; 29 print DATA join("\n", @$users); 30 ################################################## 31 </%perl> 32 33 <TABLE> 34 35 % ################################################ 36 % # Display Edit Table 37 % ################################################ 38 % my $count = 0; 39 % foreach my $user (@$users) { 40 % $count++; 41 42 <TR><TD> 43 <FONT FACE=ARIAL> <% $count %>. </FONT> 44 </TD><TD> 45 <INPUT TYPE="checkbox" NAME="switchlist" 46 VALUE="<% $count-1 %>"> 47 <FONT FACE=ARIAL> <B> <% $user %> </B> </FONT> 48 </TD></TR> 49 </FONT> 50 51 % } 52 53 </TABLE> 54 55 <FONT FACE=ARIAL> 56 <INPUT TYPE="SUBMIT" NAME=switch 57 VALUE="Switch Selected Entries"> 58 59 <HR> 60 <INPUT TYPE="TEXT" NAME=newname VALUE=""> 61 <INPUT TYPE="SUBMIT" NAME=new VALUE="Add Name"> 62 63 <HR> 64 <INPUT TYPE="SUBMIT" NAME=view 65 VALUE="Back to List"> 66 </FONT> 67 68 </FORM>
Zwischen Zeile 35 und 51 stellt edit.html
die Tabelle mit
eingebauten
Checkbox-Knöpfen dar, die alle switchlist
heissen und
als Werte die Indexpositionen 0 bis @$users - 1
aufweisen.
Klickt der Benutzer zwei davon an und drückt
den ``Switch Selected Entries''-Knopf, geht der Browser
zurück nach pingpong.html
, welches wegen des in Zeile
10 von edit.html
gesetzten edit
-Parameters wieder
edit.html
hereinholt. $switchlist
zeigt dann auf ein Array,
das als Elemente die beiden Indexpositionen von @$users
enthält, die es zu vertauschen gilt. Die Zeilen 19 und 20 tun
genau dies.
Ist hingegen $new
gesetzt, will der Benutzer einen neuen Spieler
einfügen, dessen Name in $newname
steht. Zeile 24 schiebt ihn
ans Ende der Tabelle.
Drückt der Benutzer hingegen den Knopf ``Back to List'', setzt
das Formular in Zeile 64 von edit.html
den CGI-Parameter view
und das kurz darauf vom Browser
kontaktierte pingpong.html
zeigt wegen seiner Zeile 19 trotz
gesetztem edit
wieder die nicht-editierbare Tabelle an.
HTML::Mason
läuft üblicherweise in einem mit
mod_perl
-beschleunigten Apache-Server. Wer hierzu zu faul ist,
lese sich den nächsten Abschnitt ``Installation für Faule'' durch.
Aber mod_perl
ist schnell installiert, hierzu
holt man es sich unter
http://perl.apache.org/dist/\ mod_perl-1.24_01.tar.gz
ab (nicht die Version 1.24 vom CPAN, die enthält nämlich einen Fehler),
den Apache 1.3.14 von www.apache.org
und entpackt beide:
gzip -dc apache_1.3.14.tar.gz \ | tar xfv - gzip -dc mod_perl-1.24_01.tar.gz \ | tar xfv -
Man sollte sich überlegen, wo der Apache landen soll,
wir nehmen einfach einmal /www/apache
an. Dort legen
wir ein zusätzliches mason
-Verzeichnis an, mit einem
comp
- und einem data
-Unterverzeichnis:
mkdir /www/apache/mason mkdir /www/apache/mason/comp mkdir /www/apache/mason/data chown nobody /www/apache/mason/data
Das data
-Verzeichnis muss vom Benutzer des Webservers beschreibbar
sein, üblicherweise nobody
.
Dann wechselt man ins mod_perl
-Verzeichnis und konfiguriert
sowohl mod_perl
als auch den Apache auf einen Rutsch.
Soll der Apache nach /www/apache
, geht das so:
cd mod_perl-1.24_01 perl Makefile.PL \ APACHE_PREFIX=/www/apache \ DO_HTTPD=1 \ USE_APACI=1 \ EVERYTHING=1 make make install
Dies konfiguriert, compiliert, linkt und installiert
sowohl mod_perl
als auch den Apache. make install
erfordert die notwendigen Benutzerrechte zum Beschreiben der Perl-Installation
und der Webserver-Verzeichnisse.
In die Datei conf/httpd.conf
der Apache-Installation (im Beispiel unter
/www/apache/conf/http.conf
) muss dann noch folgende Sequenz:
# Additions to your httpd.conf PerlRequire \ /www/apache/mason/handler.pl
Alias /mason /www/apache/mason/comp <Location /mason> SetHandler perl-script PerlHandler HTML::Mason </Location>
Nun kommt HTML::Mason
an die Reihe. Hierzu eignet sich am
besten die CPAN-Shell:
perl -MCPAN -eshell cpan> install MLDBM cpan> install HTML::Mason
HTML::Mason
setzt MLDBM
voraus, was der obige Aufruf gleich
mitinstalliert.
Die HTML::Mason
-Distribution enthält noch einen Handler, den
der Apache braucht, deswegen kopieren wir ihn von dort ins
Webserververzeichnis:
cd ~/.cpan/build/HTML::Mason cp eg/handler.pl \ /www/apache/mason/handler.pl
Das Verzeichnis hierfür ist beliebig wählbar, muss aber dem
vorher in httpd.conf
gesetzten entsprechen.
Angepasst wird der Initialisierungshandler in
/www/apache/mason/handler.pl
hernach, indem mit einem
Editor die beiden dort enthaltenen Platzhalter
<component root>
und
<data directory>
auf
die vorher angelegte Mason-Dokumentwurzel umgebogen werden,
also beispielsweise /www/apache/mason/comp
und /www/apache/mason/data
.
Anschließend wird der Apache mit
/www/apache/bin/apachectl start
hochgefahren. In der Standardeinstellung lauscht er auf Port
8080, wer auf dem Standardport 80 fahren will, muss dies in
conf/httpd.conf
unter Port
einstellen (und ihn anschließend unter
root
hochfahren).
Anschließend müssen die drei Skripts pingpong.html
,
display.html
und edit.html
nach /www/apache/mason/comp
wandern. Die in Zeile 35 in pingpong.html
eingestellte Datei
(im Beispiel tt.dat
) muss vom Benutzer des Webservers (nobody
)
beschreibbar sein. Der Pingpong-Administrator darf sie übrigens auch
manuell mit einem Editor verändern, um Funktionen auszuführen,
die das Browser-Interface nicht anbietet, wie zum Beispiel das
Löschen von Spielern aus der Tabelle.
Stellt man dann den Browser auf
http://localhost:8080/\ mason/pingpong.html
ein (falls als Port 80 gewählt wurde, darf die Portangabe entfallen),
sollte sich eine erste Tabelle gemäß des Inhalts der Spielerdatei
tt.dat
zeigen.
Wer den ganzen Aufwand mit mod_perl
scheut und nur mit HTML::Mason
herumspielen will, kann ein CGI-Skript nach Listing ttm.pl
nutzen und den Browser darauf zeigen:
http://localhost/cgi-bin/ttm.pl
So läuft die Pingpong-Tabelle zwar langsam aber unabhängig vom verwendeten Webserver. Spielt fleißig Pingpong!
01 #!/usr/bin/perl -w 02 03 my $ROOT = "/www/apache/mason"; 04 my $COMP_PATH = "$ROOT/comp"; 05 my $DOC_PATH = "$ROOT/data"; 06 07 use CGI qw(:all); 08 use HTML::Mason; 09 10 print header(); 11 my $outbuf; 12 my $parser = HTML::Mason::Parser->new(); 13 my $interp = HTML::Mason::Interp->new( 14 parser => $parser, 15 comp_root => $COMP_PATH, 16 data_dir => $DOC_PATH, 17 out_method => \$outbuf ); 18 19 %params = CGI::Vars(); 20 21 # Multi-Werte in Arrays transformieren 22 foreach $param (keys %params) { 23 my @values = split /\0/, $params{$param}; 24 if(@values > 1) { 25 $params{$param} = \@values; 26 } 27 } 28 29 my $retval = $interp->exec("/pingpong.html", %params); 30 31 print $outbuf;
HTML::Mason
Home Page, http://masonhq.com
Michael Schilliarbeitet als Software-Engineer bei Yahoo! in Sunnyvale, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com. |