cgicorner.ch

Informationen rund um Perl/CGI

Sie sind hier: Home > CGI Hilfe > Tutorial > Kapitel 11a - Formparsing

Tutorial - Kapitel 11: Beispiel: Form-Parsing

Voraussetzungen für dieses Kapitel

  • Grundlegende HTML-Kenntnisse
  • Webserver mit Perl/CGI-Unterstützung

Dieses Script beinhaltet drei Komponenten:

  • demoform.htm: eine HTML-Seite mit einem kleinen Formular
  • output.dat: eine HTML-Seite, welche die geparsten Ergebnisse enthält.
  • formparser.cgi: das Script, welches das Formular parst

Sinn dieses Scriptes ist es, die eigentliche Antwortseite in eine separate Datei (output.dat) auszulagern und so Layout von Scriptlogik zu trennen.

Sinn dieses Scriptes ist es, die eigentliche Antwortseite in eine separate Datei (output.dat) auszulagern und so Layout von Scriptlogik zu trennen. Anpassungen am Ergebnis des Scripts können also ohne Perl-Kenntnisse vorgenommen werden.

Das Formular (demoform.htm)

<html>
<head>
  <style type="text/css">
    body { font-family: Verdana, Arial, Univers, Helvetica; }
  </style>
</head>
<body>

<form action="/cgi-bin/formparser.cgi" method="post">

<table border="0">
  <tr>
    <td>Vorname *</td>
    <td><input type="text" name="vorname"/></td>
  </tr>
  <tr>
    <td>Name *</td>
    <td><input type="text" name="name"/></td>
  </tr>
  <tr>
    <td>Strasse</td>
    <td><input type="text" name="strasse"/></td>
  </tr>
  <tr>
    <td>PLZ</td>
    <td><input type="text" name="plz"/></td>
  </tr>
  <tr>
    <td>Ort</td>
    <td><input type="text" name="ort"/></td>
  </tr>
  <tr>
    <td>E-Mail *</td>
    <td><input type="text" name="email"/></td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td><input type="submit" value="Absenden"/></td>
  </tr>
</table>

* = Pflichtfeld

</form>

</body>
</html>

Ausgabe-Template (output.dat)

Das Ausgabe-Template ist eine reine HTML-Seite. Dabei werden dann später alle Kommentare durch die entsprechenden Werte aus dem Formular ersetzt. <!--vorname--> wird also durch das Script automatisch durch den Wert des Formularfeldes "vorname" ersetzt werden.

<html>
<head>
  <style type="text/css">
    body { font-family: Verdana, Arial, Univers, Helvetica; }
  </style>
</head>
<body>

Hallo <!--vorname--><br/>
Vielen Dank für das Absenden des Formulars.
Hier wird nun nochmals deine komplette Adresse ausgegeben:<br/>
<!--vorname--> <!--name--><br/>
<!--strasse--><br/>
<!--plz--> <!--ort--><br/><br/>
Deine Mail-Adresse lautet &uuml;brigens: <!--email-->

</body>
</html>

Schon jetzt ist klar: Formular und Ergebnisseite können auch von jemanden bearbeitet werden, welcher absolut keine Ahnung von Perl hat. Ein klares Zeichen, dass Layout und Logik des Scriptes ideal getrennt sind.

Das Kernstück: formparser.cgi

Das Script bildet das Kernstück unseres Beispiels. Grundsätzlich passiert nun folgendes: Das Script enthält die Daten aus dem Formular. Diese werden wir gleich zu Beginn in einen Hash %FORM einlesen lassen, so dass $FORM{"vorname"} also den Wert des Feldes "vorname" enthalten wird.

In einem zweiten Schritt werden wir die output.dat (welche übrigens im gleichen Verzeichnis wie das CGI-Script gespeichert werden muss) zeilenweise einlesen und alle Felder durch deren Inhalt ersetzen. Weitere Aktionen nimmt das Script nicht vor. Denkbar wären aber die Speicherung der Adressdaten in einer Datei und/oder die Weiterleitung der Daten per Mail an den Webmaster. Beides sollten Sie mit Ihren Kenntnissen eigentlich bereits implementieren können.

Das Script nimmt nur eine ganz rudimentäre Prüfung der Daten vor und beendet sich bei einem Fehler einfach. Korrekterweise müsste man natürlich bei einem Fehler eine passende Fehlermeldung ausgeben, darauf wird aber aus Komplexitätsgründen verzichtet.

Kommentare befinden sich direkt im Script.

#!/usr/bin/perl
# Beispiel-Script: Form-Parser
# Kommentare befinden sich direkt im Source-Code
# Autor: Jürg Sommer / Letzte Änderung: 16. Januar 2012

# Fehlermeldungen detailiert an Browser ausgeben
use CGI::Carp qw(fatalsToBrowser);

# Dateiname der Template-Datei
my $dataFile="output.dat";

# Formulardaten in %FORM einlesen
my %FORM;
&readForm;

# Formular-Prüfungen
if ($FORM{"vorname"} eq "") {	# Fehler, wenn Vorname leer
  die("Vorname muss ausgefüllt sein");
}
# Fehler, wenn Nachname noch andere Zeichen ausser den aufgeführten enthält
if ($FORM{"vorname"} =~ m/[^A-Z\-\.éèêâàáúûùç\'öäüöäü]/i) {
  die("Der Vorname enthält ungültige Zeichen...");
}
if ($FORM{"name"} eq "") {	# Fehler, wenn Nachname leer
  die("Nachname muss ausgefüllt sein");
}
# Fehler, wenn Nachname noch andere Zeichen ausser den aufgeführten enthält
if ($FORM{"name"} =~ m/[^A-Z\-\.éèêâàáúûùç\'öäüöäü]/i) {
  die("Der Nachname enthält ungültige Zeichen...");
}
# Syntaxprüfung Mailadresse
if ($FORM{email} !~ m/^[a-z0-9\-_\.]+\@[a-z0-9\-_\.]+\.[a-z]{2,}$/i) {
  die("Gültige Mailadresse erforderlich");
}

# HTML-Grundgerüst für Seite
print "Content-type: text/html\n\n";

# Template öffnen und zeilenweise einlesen
open(TEMPLATE, $dataFile);

while (<TEMPLATE>) {

  # die Kernfunktion: suche nach Kommentar <!--xyz--> und ersetzen
  # durch den entsprechenden Wert aus dem vorhergehenden Formular
  $_ =~ s/<!--(.*?)-->/$FORM{$1}/g;

    # (modifizierte) Zeile ausgeben
    print $_;

}

# Template schliessen
close(TEMPLATE);


###########################################################################
sub readForm { # Parameter in %FORM einlesen
  my ($buffer,@pairs,@pair,$i);
  if ($ENV{'REQUEST_METHOD'} eq "GET") {
    $buffer = $ENV{'QUERY_STRING'};
  } else {
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
  }
  @pairs = split(/&/, $buffer);
  foreach (@pairs) {
    @pair = split(/=/, $_, 2);
    for ($i=0;$i<2;$i++) {
      $pair[$i] =~ tr/+/ /;
      $pair[$i] =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    }
    $FORM{$pair[0]} = $pair[1];
  }
}

Die elementare Zeile in diesem Script lautet

$_ =~ s/<!--(.*?)-->/$FORM{$1}/g;

Hierbei wird jedes Vorkommen von "<!--feldname-->" durch den entsprechenden Wert des Feldes im vorangestellten Formular ersetzt. So funktioniert das Script völlig unabhängig von den verwendeten Feldnamen, d.h. im Formular kann jederzeit ein zusätzliches Feld eingefügt (z.B. <input type="text" name="land"/>) und dann im Template mit <!--land-->

Hierbei wird jedes Vorkommen von "<!--feldname-->" durch den entsprechenden Wert des Feldes im vorangestellten Formular ersetzt. So funktioniert das Script völlig unabhängig von den verwendeten Feldnamen, d.h. im Formular kann jederzeit ein zusätzliches Feld eingefügt (z.B. <input type="text" name="land"/>) und dann im Template mit <!--land--> ausgegeben werden. Einzig für neue Pflichtfelder sind Eingriffe ins Script notwendig.

Wie geht's weiter?

Nachdem Sie dieses Beispiel genauer betrachtet haben, können Sie wieder zurück zum Kapitel 11 des Tutorials.