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. |