#!/usr/bin/perl -wT use DBI; use CGI ":standard"; use CGI::Carp "fatalsToBrowser"; use Digest::MD5 qw(md5_hex); use strict; ##### # The structure of the mySQL koan table follows. # # CREATE TABLE zen ( # id int(11) NOT NULL auto_increment, # koan text, # PRIMARY KEY (id) # ) TYPE=MyISAM; ##### # The structure of the users table is # # CREATE TABLE zenusers ( # username char(12) NOT NULL default '', # passwd char(20) NOT NULL default '', # PRIMARY KEY (username) # ) TYPE=MyISAM; # # To create a user, make sure to use mySQLs password() function. # To create a user from the mySQL client: # insert into zenusers values("username",password("your_pass")); ##### # My idea around this is to include it as an SSI on a page. # Embed the SSI in a paragraph, and use CSS to control the look # of the text, with "
" for instance.
#
# This script isn't incredibly secure, it could be made more so
# by using a random encrypted cookie and storing that in a table
# to use for future authentication.
# However, enough is enough. You can set the seed for the md5 digest
# to whatever you want.
#
# I know I should probably use HTML::Parser to strip tags but for
# the life of me I couldn't figure it out. Maybe down the road. . .
##### Connect
my $dbh;
$dbh = DBI->connect( "dbi:mysql:yourdb","username","password")
or die("Can't connect: ", $dbh->errstr);
##### End connect.
my $q = new CGI;
##### Flow control.
if ($q->param("koan")){# if "koan" is defined, do this loop.
my $date=mydate();
# if cookie is set, and correct, allow access to other functions
if ($q->cookie("valid") eq md5_hex($date)){
if ($q->param("koan") eq 'addkoan'){
addkoan();
} elsif ($q->param("koan") eq 'createkoan'){
createkoan();
} elsif ($q->param("koan") eq 'listkoan'){
listkoan();
} elsif ($q->param("koan") eq 'editkoan'){
editkoan();
} elsif ($q->param("koan") eq 'controlkoan'){
controlkoan();
} else {
#if "koan" isn't in the above list, show a koan.
showkoan();
}
} else {
login();
}
} else {
# if "koan" and cookie isn't defined, do this loop.
showkoan();
}
##### Creates form to manage koans
sub controlkoan {
print
$q->header(),
$q->start_html("-title"=>"Control Panel for Koans"),
$q->h2("Control Panel for Koans"),
$q->br,
$q->a({-href =>"/cgi-bin/zen.pl?koan=createkoan"},"Add a koan"),
$q->br,
$q->a({-href =>"/cgi-bin/zen.pl?koan=listkoan"},"List all koans"),
$q->br,
$q->a({-href =>"/cgi-bin/zen.pl?koan=editkoan"},"Edit koans"),
$q->end_html();
}
##### Lists all koans in order by id.
sub listkoan {
my $tth=$dbh->prepare("select koan from zen order by id")
or dienice("Can't connect: ",$dbh->errstr);
$tth->execute;
print $q->header();
while (my $koan = $tth->fetchrow_array){
print $koan,
$q->hr();
}
}
##### Login and Authenication
sub login{
if ($q->param("username")){
# if username is defined, check again zenusers table.
my $passwd=$q->param("passwd");
my $username=$q->param("username");
my $sth=$dbh->prepare("select username from zenusers where (passwd=password(\"$passwd\")".
"and username=\"$username\")") or die("can't execute query ",$dbh->errmsg);
$sth->execute;
my $usertest= $sth->fetchrow_array;
if ($usertest){
# if it matches a username, set the cookie goto controlkoan()
my $date=mydate();
my $value= md5_hex($date);
my $cookie = $q->cookie(-name=>"valid",
-value=>"$value");
print "Set-Cookie: $cookie\n";
print $q->redirect("/cgi-bin/zen.pl?koan=controlkoan");
} else {
# if it doesn't match, cryptically redirect and showkoan().
print $q->redirect("/cgi-bin/zen.pl");
}
} else {
# if username isn't defined, allow the user to attempt login.
print
$q->header(),
$q->start_html("-title"=>"Control Panel for Koans"),
$q->h2("Login to control koans"),
$q->start_form(-method =>"post", -action =>"/cgi-bin/zen.pl"),
$q->hidden(-name=>"koan",-default=>"login",-override=>"true"),
$q->br,
$q->b("Username:"),
$q->textfield(-name=>"username"),
$q->br,
$q->b("Password:"),
$q->password_field(-name=>"passwd"),
$q->br,
$q->submit("Login"),
$q->end_form(),
$q->end_html();
}
}
##### Lists all koans, allowing for editing. Changes "
" back to \n.
sub editkoan {
my $tth=$dbh->prepare("select id,koan from zen order by id")
or dienice("Can't connect: ",$dbh->errstr);
$tth->execute;
print
$q->header(),
$q->start_html("-title"=>"Add Koan"),
$q->h2("Update Koans"),
$q->h3("Blank lines will be retained, all HTML tags will be removed.");
while (my ($id,$koan) = $tth->fetchrow_array){
$koan =~ s/
/\n/g;
print $q->br,
$q->start_form(-method =>"post", -action =>"/cgi-bin/zen.pl"),
$q->textarea(-name=>"koantext",-default=>"$koan",
"wrap=\"virtual\" cols=\"70\" rows=\"15\""),
$q->hidden(-name=>"koan",-default=>"addkoan",-override=>"true"),
$q->hidden(-name=>"id",-default=>"$id",-override=>"true"),
$q->br,
$q->submit("Update This Koan"),
$q->reset(),
$q->end_form();
}
print $q->end_html();
}
##### adds or updates a koan depending on where the request comes from.
sub addkoan {
my $koan = $q->param("koantext");
$koan =~ s/<([^>])*>//g;
$koan =~ s/\n/
/g;
my $id=$q->param("id");
if ($q->param("id")){
my $rth=$dbh->prepare("update zen set koan=(?) where id=$id ") or die();
$rth->execute($koan);
} else {
my $rth=$dbh->prepare("insert into zen (koan) values (?)") or die();
$rth->execute($koan);
}
print
$q->header(),
$q->start_html("-title"=>"Koan Added/Updated"),
$q->h3("Koan Added/Updated"),
$q->end_html();
}
##### Creates form to add a koan.
sub createkoan {
print
$q->header(),
$q->start_html("-title"=>"Add Koan"),
$q->h2("Enter Koan"),
$q->h3("Blank lines will be retained, HTML tags will be removed."),
$q->br,
$q->start_form(-method =>"post", -action =>"/cgi-bin/zen.pl"),
$q->textarea(-name=>"koantext",
"wrap=\"virtual\" cols=\"70\"rows=\"15\""),
$q->hidden(-name=>"koan",-default=>"addkoan",-override=>"true"),
$q->br,
$q->submit("Add Koan"),
$q->reset(),
$q->end_form(),
$q->end_html();
}
##### This selects and displays a random koan.
sub showkoan {
srand(time() ^ ($$ + ($$ << 15)) );
my (@ids,$rth,$id,$tth,$koan,$selid);
$rth=$dbh->prepare("select max(id) from zen order by id")
or die("Can't connect: ", $dbh->errstr);
$rth->execute;
$id=$rth->fetchrow_array;
$selid=int(rand($id)+1);
$tth=$dbh->prepare("select koan from zen where id=$selid")
or die("Can't connect: ",$dbh->errstr);
$tth->execute;
$koan = $tth->fetchrow_array;
print
$q->header(),
$koan;
}
##### This creates the date for the md5 digest
sub mydate{
my ($sec,$min,$hr,$mday,$yr,$yday,$isdist,$fixmo,$mon,$timestr2);
($sec,$min,$hr,$mday,$mon,$yr,$yday,$isdist)= localtime(time);
$fixmo = $mon + 1;
$timestr2= sprintf("%04d-%02d-%02d",($yr+1900),$fixmo,"01");
return $timestr2;
}