#!/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; }