XSign: Unterschriftenliste
Dieses Skript erlaubt die Einrichtung einer Online-Unterschriftensammlung.
Source Code
|
Perl Sourcecode
|
| xsign.pl |
Das Skript xsign.pl |
|
Achtung: Sollte beim obigen Download-Link fehlerhafterweise als Dateiname "xload.cgi"
angegeben sein, ignorieren Sie dies und benennen den Dateinamen um. Einige Browser ignorieren
leider den Standard zur Übermittlung von Dateinamen...
|
Wirkungsweise
Eintragsformular
Es handelt sich um ein ganz normales Formular:
Der zugehörige HTML-Code enthält nichts besonderes:
<form action="/cgilocal/xsign/xsign.pl">
<input type="hidden" name="sign" value="demo">
Ihr Vorname lautet:
<input type="text" name="vorname" size="20">
<br>
Ihr Nachname lautet:
<input type="text" name="nachname" size="20">
<br>
Sie kommen aus welchem Ort:
<input type="text" name="ort" size="30">
<br>
Haben Sie eine Webadresse (URL)?
<input type="text" name="url" size="30">
<br>
Wollen Sie noch eine kleine Notiz hinterlassen?
<br>
<textarea name="notiz" rows="4" cols="60"></textarea>
<br><br>
Ich stimme der Veröffentlichung meines Eintrags zu:
<input type="checkbox" name="valid" value="1">
<input type="submit" value=" Abschicken ">
</form>
Wichtig ist diese Zeile:
<input type="hidden" name="sign" value="demo">
Hier geben Sie an, welche Zieldatei gemeint ist. Wobei dies hier nicht der Dateiname ist,
sondern der Alias für den Dateinamen. Der echte Dateiname wird nicht über Web übertragen, sondern
wird im Skript in der Zeile 46 definiert.
Liste anzeigen
Die Unterschriftenliste kann man sich am Besten über ein SSI-Skript anzeigen, bzw. ueber
den Skriptaufruf, welcher dann in einem eigenen JavaScript-Fenster angezeigt wird.
Beispiel für den SSI-Aufruf:
#!/local/bin/perl
##############################################################################
# $Id: xsign.pl,v 1.3 2003/05/23 17:02:21 xwolf Exp $ #
# COPYRIGHT NOTICE #
# Copyright 2000 Wolfgang Wiese All Rights Reserved. #
# EMail: xwolf@xwolf.com #
# URL : http://www.xwolf.com #
# #
# This script may be used and modified free of charge by anyone so long as #
# this copyright notice and the comments above remain intact. By using this #
# code you agree to indemnify Wolfgang Wiese from any liability that #
# might arise from it's use. #
# #
# Selling the code for this program without prior written consent is #
# expressly forbidden. In other words, please ask first before you try and #
# make money off of my program. #
# #
# Obtain permission before redistributing this software over the Internet or #
# in any other medium. In all cases copyright and header must remain intact.#
##############################################################################
# Last Modified on: $Date: 2003/05/23 17:02:21 $
# By: $Author: xwolf $
# Version: $Revision: 1.3 $
##############################################################################
use strict;
my $THISURL = "/cgilocal/xsign/xsign.pl";
# Die URL zum Skript
my @NEEDED_VALS = ("vorname", "nachname", "valid");
# Diese Felder MUESSEN ausgefuellt sein in der Eingabe
my $CHECK_DOUBLESUBMIT = 1;
# Soll ueberprueft werden, ob jemand schon mal unterschrieben hat...
my $MAXLENGTH_NOTIZ = 200;
# Wieviel Zeichen duerfen in der Notiz maximal drin sein
my $OUTPUT_LINE_LAYOUT = "
#URLREFSTART##VORNAME# #NACHNAME##URLREFEND# #ORT# | #ORGANISATION# | #ZEIT# | #NOTIZ# |
";
# Wie soll die Ausgabezeile aussehen
# variablen: Die Eingabefelder mit rauten umgeben, sowie #ZEIT# fuer die Zeit des Eintrages
# und #SWITCHSTRING# fuer die Wechselfarbe
my $ERROR_LINE = "
Es konnten keine Daten gefunden werden.
|
";
# Zeile, falls die DB leer ist...
my $SWITCH_COLOR_TWO = "#ffffff";
my $SWITCH_COLOR_ONE = "#DDDDDD";
# Wechselfarben fuer die Zeilen
my $MAX_DISPLAY_LINES = 20;
# Wieviele Unterschriften sollen per Standard ausgegeben werden?
my %INDEX = ("demo", "../../misc/xsign-demoliste.csv");
# Index der Unterschriftsdateien
##############################################################################
my $AUSGABE_LAYOUT = "#SYSTEMMELDUNG# \n
Unterschriftenliste
\n
\n
#ENTRIES#\n
\n
| \n
#PREVPAGE# #NEXTPAGE#\n
| \n
\n
\n
";
##############################################################################
# Main
##############################################################################
my %in = &ReadParse;
# Parsen der Eingabewerte
my $thisip = $ENV{'REMOTE_ADDRESS'} || $ENV{'REMOTE_HOST'} || $ENV{'HTTP_X_FORWARDED_FROM'};
my $thistime = time;
my $do_edit;
my $DONEPrintHeader;
# open(STDERR,">test.txt");
if ($in{'view'}) {
&DisplayEntries;
} else {
$do_edit =1;
&ParseInput;
&CheckInput;
&SaveEntry;
&DisplayEntries;
}
exit;
##############################################################################
# Subroutinen
##############################################################################
sub DisplayEntries {
if (not $INDEX{$in{'sign'}}) {
Fehlermeldung("Das von Ihnen angewaehlte Dokument ist ungueltig.");
}
my @liste;
my $start = $in{'start'};
my $end = $in{'end'};
my $thisline;
my $i;
my $file = $INDEX{$in{'sign'}};
my ($name, $vorname, $url, $zeit, $ip, $organisation, $ort, $notiz);
my ($sek,$minute,$stunde,$tag,$monat,$jahr,$wtag,$ytag,$isdst);
my $zeitstring;
my $switch;
my $switchstring;
my $alle_eintraege;
my $sysmess;
my $nextpage;
my $prevpage;
my $URLREFSTART;
my $URLREFEND;
&PrintHeader;
if ($do_edit) {
$sysmess = "
Vielen Dank für Ihre Unterschrift!";
} else {
$sysmess = "";
}
if (not (-r $file)) {
$alle_eintraege = $ERROR_LINE;
} else {
open(f1,"<$file");
@liste =
;
close f1;
if ($#liste==-1) {
$alle_eintraege = $ERROR_LINE;
} else {
if ($start >= $#liste) {
$start = $#liste - $MAX_DISPLAY_LINES;
}
if ($start <=0) {
$start = 0;
}
if ($end <=0) {
$end = $start+$MAX_DISPLAY_LINES;
}
if ($end > $#liste) {
$end = $#liste;
}
if ($end < $#liste) {
$nextpage = "?start=$end";
} else {
$nextpage = "";
}
if ($start >= $MAX_DISPLAY_LINES) {
$prevpage = $start-$MAX_DISPLAY_LINES-1;
$prevpage = "?start=$prevpage";
} else {
$prevpage = "";
}
for ($i=$start; $i<=$end; $i++) {
if ($switch) {
$switch =0;
$switchstring = $SWITCH_COLOR_TWO;
} else {
$switch =1;
$switchstring = $SWITCH_COLOR_ONE;
}
chomp($liste[$i]);
($name, $vorname, $url, $zeit, $ip, $organisation, $ort, $notiz) = split(/\t/,$liste[$i],8);
($sek,$minute,$stunde,$tag,$monat,$jahr,$wtag,$ytag,$isdst) = localtime($zeit);
$monat++;
$jahr += 1900;
if ($minute < 10) {
$minute = "0$minute";
}
if (not $ort) {
$ort = " ";
}
if (not $notiz) {
$notiz = " ";
} else {
$notiz = "$notiz";
}
if (not $organisation) {
$organisation = " ";
}
if ($url) {
$URLREFSTART = "";
$URLREFEND = "";
} else {
$URLREFSTART = "";
$URLREFEND = "";
}
$zeitstring = "$tag.$monat.$jahr, $stunde:$minute Uhr";
$thisline = $OUTPUT_LINE_LAYOUT;
$thisline =~ s/#SWITCHSTRING#/$switchstring/gi;
$thisline =~ s/#VORNAME#/$vorname/gi;
$thisline =~ s/#NACHNAME#/$name/gi;
$thisline =~ s/#ORT#/$ort/gi;
$thisline =~ s/#URL#/$url/gi;
$thisline =~ s/#URLREFSTART#/$URLREFSTART/gi;
$thisline =~ s/#URLREFEND#/$URLREFEND/gi;
$thisline =~ s/#ORGANISATION#/$organisation/gi;
$thisline =~ s/#NOTIZ#/$notiz/gi;
$thisline =~ s/#ZEIT#/$zeitstring/gi;
$thisline =~ s/#IP#/$ip/gi;
$thisline =~ s/#([a-zA-Z0-9]+)#//gi;
$alle_eintraege .= "$thisline\n";
}
}
}
my $np_url;
my $pp_url;
if ($nextpage) {
$np_url = "Nächste Seite";
} else {
$np_url = "";
}
if ($prevpage) {
$pp_url = "Vorherige Seite";
} else {
$pp_url = "";
}
$AUSGABE_LAYOUT =~ s/#NEXTPAGE#/$np_url/gi;
$AUSGABE_LAYOUT =~ s/#PREVPAGE#/$pp_url/gi;
$AUSGABE_LAYOUT =~ s/#SYSTEMMELDUNG#/$sysmess/gi;
$AUSGABE_LAYOUT =~ s/#ENTRIES#/$alle_eintraege/gi;
print "$AUSGABE_LAYOUT
\n";
}
################################################################################
sub PrintHeader {
if (not $DONEPrintHeader) {
print "Content-type: text/html\n\n";
$DONEPrintHeader =1;
# return 1;
} else {
# return 0;
}
}
##############################################################################
sub Fehlermeldung {
my ($fehlertext) = $_[0];
&PrintHeader;
print "Fehler\n";
print "\n";
print "Fehlermeldung
\n";
print "Bei der Verarbeitung des Programmes ist ein Fehler aufgetreten:\n";
print "$fehlertext\n";
print "
\n";
print "\n";
exit(0);
}
##############################################################################
sub SaveEntry {
my $file = $INDEX{$in{'sign'}};
my $i;
my @liste;
my ($name, $vorname, $url, $zeit, $ip, $organisation, $ort, $notiz);
if ($CHECK_DOUBLESUBMIT) {
open(f1,"<$file");
@liste = ;
close f1;
for ($i=0; $i<=$#liste; $i++) {
($name, $vorname, $url, $zeit, $ip, $organisation, $ort, $notiz) = split(/\t/,$liste[$i],8);
}
if (($name eq $in{'nachname'}) && ($vorname eq $in{'vorname'}) && ($thisip eq $ip)) {
&Fehlermeldung("Sie haben bereits unterschrieben.","Eingabefehler");
}
}
open(f1,">>$file");
print f1 "$in{'nachname'}\t";
print f1 "$in{'vorname'}\t";
print f1 "$in{'url'}\t";
print f1 "$thistime\t";
print f1 "$thisip\t";
print f1 "$in{'organisation'}\t";
print f1 "$in{'ort'}\t";
print f1 "$in{'notiz'}\n";
close f1;
}
##############################################################################
sub ParseInput {
my $key;
foreach $key (keys %in) {
$in{$key} =~ s/<([^>]|\n)*>//ig;
$in{$key} =~ s/[\n\r]/ /g;
}
if (not &isURL($in{'url'})) {
$in{'url'} = "";
}
}
##############################################################################
sub CheckInput {
my $i;
my $feldname;
my $fehler;
if (not $INDEX{$in{'sign'}}) {
$fehler .= "Die von Ihnen eingegebenen Daten enthalten eine Zugriffsverletzung. Bitte überprüfen Sie die Gültigkeit des Eingabeformulars.\n";
} else {
for ($i=0; $i<=$#NEEDED_VALS; $i++) {
if (not $in{$NEEDED_VALS[$i]}) {
$feldname = ucfirst($NEEDED_VALS[$i]);
$fehler .= " Das Feld \"$feldname\" wurde nicht ausgefüllt.\n";
}
}
}
if (length($in{'notiz'}) > $MAXLENGTH_NOTIZ) {
$fehler .= "Die Notiz von Ihnen ist länger als $MAXLENGTH_NOTIZ Zeichen.\n";
}
if ($fehler) {
$fehler = "Bei der Eingabe traten Fehler auf:\n\n
Ihre Daten konnten nicht gespeichert werden.";
&Fehlermeldung($fehler);
}
}
##############################################################################
sub isURL {
my $askurl =$_[0];
$askurl =~ s/[<>\|;\(\)\$^!\^\[\]\"\'\`]//g;
if (length($askurl) < 11) {
return 0;
}
if ($askurl =~ /^([a-z]+):\/\/([^:\/]+)(:[0-9]+)?/i) {
if (index($2,".") <=0) {
return 0;
} else {
if (length($2) < 5) {
return 0;
}
$askurl = $1;
if (not ($askurl =~ /^(ftp|http|https|news|telnet)/i)) {
return 0;
}
return 1;
}
} else {
return 0;
}
}
##############################################################################
sub ReadParse {
my $buffer;
my ($namebuffer,$valuebuffer);
my %result;
if ($ENV{'REQUEST_METHOD'} eq "GET") { $buffer = $ENV{'QUERY_STRING'}; }
else { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
if (!($buffer)) {$buffer=substr($ENV{'PATH_INFO'},1,length($ENV{'PATH_INFO'}));}
if (!($buffer)) {$buffer=@ARGV; }
my @nvpairs = split(/&/,$buffer);
my $pair;
my %value_checkbox;
foreach $pair (@nvpairs)
{
($namebuffer, $valuebuffer) = split(/=/, $pair);
$valuebuffer =~ tr/+/ /;
$valuebuffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if (exists($result{$namebuffer})) {
if ($result{$namebuffer} ne '#VALUE_CHECKBOX') {
push(@{$value_checkbox{$namebuffer}},$result{$namebuffer});
$result{$namebuffer}="#VALUE_CHECKBOX";
}
push(@{$value_checkbox{$namebuffer}},$valuebuffer);
} else {
$result{$namebuffer}=$valuebuffer;
}
}
return %result;
}
##############################################################################
Dies sieht dann wie folgt aus:
<!--#include virtual="/cgilocal/xsign/xsign.pl?sign=demo&view=1" -->
Alternativ kann man natürlich auch via Link auf die Liste gehen:
Liste aufrufen
Die Ergebnisse, das heißt die Unterschriften, werden als CSV-Datei gespeichert
und können als solche auch in anderen Programmen weiterverarbeitet werden.
Hier die Liste, die aus obiger Demo generiert wird: xsign-demoliste.csv.
Installation
Kopieren Sie die Dateien xmas.pl und web.pm in Ihr CGI-BIN-Verzeichnis. Setzen Sie die Ausführungsrechte
mittels CHMOD. Z.B.: chmod 755 xmas.pl.
Ändern Sie im Programm xmas.pl folgende Zeilen:
Zeile 1: #!/local/bin/perl5 |
Geben Sie hier Ihren eigenen Pfad zu Perl ein, falls er von diesem abweicht. |
Zeile 27: my $THISURL = "/cgilocal/xsign.pl"; |
Geben Sie hier die URL zum Skript an, falls Sie dieses in ein anderes Verzeichnis tun oder es
umbenennen. |
Zeile 29: my @NEEDED_VALS = ("vorname", "nachname", "valid"); |
Hier können Sie angeben, welche <input name="">-Einträge
notwendig sind, damit der Eintrag akzeptiert wird.
Mögliche Eingaben sind: vorname, nachname, ort, url, notiz, organisation |
Zeile 33: my $MAXLENGTH_NOTIZ = 200;; |
Wie lange darf das Kommentarfeld maximal sein. |
Zeile 35: my $OUTPUT_LINE_LAYOUT = "<TR bgcolor=\"#SWITCHSTRING#\"><TD>#URLREFSTART##VORNAME# #NACHNAME##URLREFEND#<BR><font size=-1>#ORT#</font></TD><TD>#ORGANISATION#</TD><TD><font size=-1>#ZEIT#</font></TD><TD>#NOTIZ#</TD></TR>"; |
Hier geben Sie an, wie eine Tabellenzeile für die Anzeige einer Unterschrift jeweils aussehen soll.
Die Variablen der Form #Name# entsprechen (ohne den #) den Namen, die Sie bei der Eingabemaske
definieren. |
Zeile 44: my $MAX_DISPLAY_LINES = 50; |
Wieveile Unterschriften sollen maximal zur selben Zeit dargestellt werden. |
Zeile 46: my %INDEX = ("demo", "../../misc/xsign-demoliste.csv"); |
Hier werden den Dateinamen, in denen die daten als CSV gespeichert werden, Aliase
zugewiesen. Die jeweilige Umfrage wird beim Webaufruf nür über einen Alias, hier demo,
geleistet. Dadurch wird verhindert, daß jemand versucht, unschöne Dateinamen
zu übergeben und Kommandos auf dem System auszuführen.
Sie können somit gleichzeitig mehrere Listen verwalten. Die Syntax ist hier immer:
"Aliasnamen" , "Pfad zur Datei",
wobei darauf zu achten ist, daß auenrum die runden Klammern erhalten bleiben und
die Dateien auch für den Webserver beschreibbar sind.
|