From eed35515bf6d201f2333cd647d802dbfd1ea3331 Mon Sep 17 00:00:00 2001 From: briandilley Date: Mon, 23 Oct 2006 22:14:15 +0000 Subject: [PATCH] Made all scripts "use strict" Implemented Captcha --- kwotes-lib.pl | 212 ++++++++++++++++++++++++++++-------- kwotes.conf.pl | 52 +++++---- kwotes.pl | 105 ++++++++++-------- kwotes.sql | 12 +- templates/default/add-kwote | 13 ++- templates/default/header | 2 +- 6 files changed, 281 insertions(+), 115 deletions(-) diff --git a/kwotes-lib.pl b/kwotes-lib.pl index 819b200..73073a9 100755 --- a/kwotes-lib.pl +++ b/kwotes-lib.pl @@ -1,32 +1,160 @@ #!/usr/bin/perl +# bring in configuration +require "kwotes.conf.pl"; + +# add a module directory +use lib qw(./deps); + # we use DBI, for it's sexy body use DBI; +use GD::SecurityImage; + +# super strict +package Lib; +use strict; # template variables -$HEADER = "header"; -$FOOTER = "footer"; -$CONTENT_DEFAULT = "default-content"; -$CONTENT_ADD = "add-kwote"; -$CONTENT_ADD_THANKS = "add-kwote-thanks"; -$CONTENT_SEARCH = "search"; -$BEFORE_LIST = "before-list"; -$AFTER_LIST = "after-list"; -$NAVIGATION = "navigation"; -$NAVIGATION_NO_BACK = "navigation-no-back"; -$NAVIGATION_NO_FORWARD = "navigation-no-forward"; -$KWOTE_ODD = "kwote-odd"; -$KWOTE_EVEN = "kwote-even"; -$CONTENT_ERROR = "error"; -$HTTP_HEADERS = "http-headers"; +$Lib::HEADER = "header"; +$Lib::FOOTER = "footer"; +$Lib::CONTENT_DEFAULT = "default-content"; +$Lib::CONTENT_ADD = "add-kwote"; +$Lib::CONTENT_ADD_THANKS = "add-kwote-thanks"; +$Lib::CONTENT_SEARCH = "search"; +$Lib::BEFORE_LIST = "before-list"; +$Lib::AFTER_LIST = "after-list"; +$Lib::NAVIGATION = "navigation"; +$Lib::NAVIGATION_NO_BACK = "navigation-no-back"; +$Lib::NAVIGATION_NO_FORWARD = "navigation-no-forward"; +$Lib::KWOTE_ODD = "kwote-odd"; +$Lib::KWOTE_EVEN = "kwote-even"; +$Lib::CONTENT_ERROR = "error"; +$Lib::HTTP_HEADERS = "http-headers"; # database connection -my $GLOBAL_DBH = undef; +$Lib::GLOBAL_DBH = undef; + +# captcha stuff +$Lib::CAPTCHA_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; +$Lib::CAPTCHA_LEN = 8; +@Lib::CAPTCHA_BG_COLORS; +push(@Lib::CAPTCHA_BG_COLORS, "\#eeceff"); +push(@Lib::CAPTCHA_BG_COLORS, "\#eeee00"); +push(@Lib::CAPTCHA_BG_COLORS, "\#00ff00"); +@Lib::CAPTCHA_FG_COLORS; +push(@Lib::CAPTCHA_FG_COLORS, "\#000000"); +push(@Lib::CAPTCHA_FG_COLORS, "\#ff0000"); +push(@Lib::CAPTCHA_FG_COLORS, "\#0000ff"); + +## +# validates a captcha +sub validate_captcha { + my ($cid, $phrase) = @_; + + # connect + my $dbh = get_db_connection(); + + # prepare and execute + my $sth = $dbh->prepare( + "SELECT count(*) as count FROM captchas WHERE id=? and LOWER(phrase)=LOWER(?);"); + $sth->bind_param(1, $cid); + $sth->bind_param(2, $phrase); + $sth->execute(); + + # get count + my $row = $sth->fetchrow_hashref(); + my $count = $row->{"count"}; + + # return + return ($count>0); + +} + +## +# serves a captcha image +sub serve_captcha { + my ($cid) = @_; + + # connect + my $dbh = get_db_connection(); + + # execute + my $sth = $dbh->prepare("SELECT phrase FROM captchas WHERE id=?"); + $sth->bind_param(1, $cid); + $sth->execute(); + + # get row + my $row = $sth->fetchrow_hashref(); + my $phrase = $row->{"phrase"} ? $row->{"phrase"} : "!ERROR!"; + + # generate captcha + my ($image_data, $mime_type) = gen_captcha($phrase); + + # send to browser + print "Content-Type: $mime_type\n\n"; + print $image_data; + +} + +## +# returns a captcha image and other info +sub gen_captcha { + my ($phrase) = @_; + my $bg = $Lib::CAPTCHA_BG_COLORS[rand()*int(@Lib::CAPTCHA_BG_COLORS)]; + my $image = GD::SecurityImage->new( + width => 120, + height => 30, + lines => (rand()*3)+1, + gd_font => 'giant', + send_ctobg => 0, + bgcolor => $bg + ); + $image->random($phrase); + $image->create( + "normalf", + "default", + $Lib::CAPTCHA_FG_COLORS[rand()*int(@Lib::CAPTCHA_FG_COLORS)] + ); + my ($image_data, $mime_type, $random_number) = $image->out(force => 'jpeg'); + return ($image_data, $mime_type); +} + +## +# generates a random captcha phrase +sub gen_captcha_phrase { + my $phrase; + for (my $i=0; $i<$Lib::CAPTCHA_LEN; $i++) { + $phrase .= substr( + $Lib::CAPTCHA_CHARS, + rand()*length($Lib::CAPTCHA_CHARS), + 1 + ); + } + + # get connection + my $dbh = get_db_connection(); + + # prepare statement + my $sth = $dbh->prepare( + "INSERT INTO captchas (phrase) VALUES (?)", + ) or return undef; + + # bind params + $sth->bind_param(1, $phrase); + + # execute + $sth->execute() or return undef; + + # return id + return ($dbh->{'mysql_insertid'}) ? + $dbh->{'mysql_insertid'} : $sth->insert_id; + +} ## # Returns a random tagline sub get_tagline { - return $TAG_LINES[ @TAG_LINES*rand() ]; + return $Conf::TAG_LINES[ @Conf::TAG_LINES*rand() ]; } ## @@ -73,25 +201,18 @@ sub cleanup { "INSERT INTO kwote_backup SELECT * FROM kwote WHERE ". "(now()-submit_dt)>? AND rating<=?" ); - $sth->bind_param(1, $KWOTE_TTL); - $sth->bind_param(2, $KWOTE_DEATH_RATING); + $sth->bind_param(1, $Conf::KWOTE_TTL); + $sth->bind_param(2, $Conf::KWOTE_DEATH_RATING); $sth->execute() or die "Couldn't backup kwotes"; # delete kwotes $sth = $dbh->prepare( "DELETE FROM kwote WHERE (now()-submit_dt)>? AND rating<=?" ); - $sth->bind_param(1, $KWOTE_TTL); - $sth->bind_param(2, $KWOTE_DEATH_RATING); + $sth->bind_param(1, $Conf::KWOTE_TTL); + $sth->bind_param(2, $Conf::KWOTE_DEATH_RATING); $sth->execute() or die "Couldn't delete kwotes"; - # delete the vote log (this doesn't affect kwote rating) - $sth = $dbh->prepare( - "DELETE FROM vote WHERE (now()-vote_dt)>?" - ); - $sth->bind_param(1, $VOTE_TTL); - $sth->execute() or die "Couldn't delete votes"; - # let em know we're good print "Kwote Database cleanup complete\n"; @@ -110,10 +231,11 @@ sub vote { # prepare statement my $sth = $dbh->prepare( "SELECT COUNT(*) as vote_count FROM vote WHERE ". - "ip_address=? AND kwote_id=?" + "ip_address=? AND kwote_id=? AND (now()-vote_dt)<=?" ); $sth->bind_param(1, $addr); $sth->bind_param(2, $kid); + $sth->bind_param(3, $Conf::SECS_BETWEEN_VOTES); # execute $sth->execute(); @@ -122,7 +244,7 @@ sub vote { my $row = $sth->fetchrow_hashref(); # check if they suck - return undef if ($row->{"vote_count"}>=$MAX_VOTES_PER_IP); + return undef if ($row->{"vote_count"}>=$Conf::MAX_VOTES_PER_IP); # prepare $sth = $dbh->prepare( @@ -134,11 +256,12 @@ sub vote { # record the vote $sth = $dbh->prepare( - "INSERT INTO vote (ip_address, kwote_id, vote_dt) ". - "VALUES (?, ?, now())" + "INSERT INTO vote (ip_address, kwote_id, vote, vote_dt) ". + "VALUES (?, ?, ?, now())" ); $sth->bind_param(1, $addr); $sth->bind_param(2, $kid); + $sth->bind_param(3, $amt); $sth->execute() or return undef; # we're good @@ -159,7 +282,7 @@ sub add_kwote { "SELECT COUNT(*) as kwote_count FROM kwote WHERE ip_address=? AND (now()-submit_dt)bind_param(1, $ip_address); - $sth->bind_param(2, $SECS_BETWEEN_KWOTES); + $sth->bind_param(2, $Conf::SECS_BETWEEN_KWOTES); # execute $sth->execute() or return undef; @@ -168,7 +291,7 @@ sub add_kwote { my $row = $sth->fetchrow_hashref() or return undef; # check if they suck - return undef if ($row->{"kwote_count"}>=$MAX_KWOTES_PER_IP); + return undef if ($row->{"kwote_count"}>=$Conf::MAX_KWOTES_PER_IP); # prepare statement my $sth = $dbh->prepare( @@ -306,14 +429,14 @@ sub list_kwotes { ## # Connect to the database sub get_db_connection { - if (!$GLOBAL_DBH) { - $GLOBAL_DBH = DBI->connect( - "dbi:$DB_TYPE:$DB_NAME:$DB_HOST", - $DB_USER, - $DB_PASS + if (!$Lib::GLOBAL_DBH) { + $Lib::GLOBAL_DBH = DBI->connect( + "dbi:".$Conf::DB_TYPE.":".$Conf::DB_NAME.":".$Conf::DB_HOST, + $Conf::DB_USER, + $Conf::DB_PASS ); } - return $GLOBAL_DBH; + return $Lib::GLOBAL_DBH; } ## @@ -351,10 +474,11 @@ sub xml_escape { # on the template sub get_template_headers { my ($template) = @_; - open(IN, "templates/$template/$HTTP_HEADERS"); + open(IN, "templates/$template/$Lib::HTTP_HEADERS"); my $data = join("",); close(IN); return $data; + } ## @@ -364,7 +488,7 @@ sub wrap_template { open(IN,"templates/$template/$template_file"); my $data = join("",); close(IN); - foreach $key (keys %vars) { + foreach my $key (keys %vars) { $data =~ s/\${$key}/$vars{$key}/ig; } return $data; @@ -381,7 +505,7 @@ sub render_template { ## # Parse form data sub parse_form { - my (@pairs, $pair, $buffer, %FORM); + my (@pairs, $pair, $buffer, %FORM, $name, $value); if ($ENV{'REQUEST_METHOD'} eq 'GET') { @pairs = split(/&/, $ENV{'QUERY_STRING'}); } elsif ($ENV{'REQUEST_METHOD'} eq 'POST') { @@ -389,7 +513,7 @@ sub parse_form { @pairs = split(/&/, $buffer); } foreach $pair (@pairs) { - local($name, $value) = split(/=/, $pair); + ($name, $value) = split(/=/, $pair); $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ tr/+/ /; diff --git a/kwotes.conf.pl b/kwotes.conf.pl index 5dc93f9..3ee6bb2 100755 --- a/kwotes.conf.pl +++ b/kwotes.conf.pl @@ -1,11 +1,15 @@ #!/usr/bin/perl + +use strict; +package Conf; + ############################ ## LOOK N FEEL ## ############################ -$SITE_NAME = "Kwotes"; +$Conf::SITE_NAME = "Kwotes"; # the name of the site -@TAG_LINES = ( +@Conf::TAG_LINES = ( "For happy goodness!", "The better kwote database.", "It blows goats!" @@ -13,63 +17,69 @@ $SITE_NAME = "Kwotes"; # tag lines to be randomly displayed # in the header -$DEFAULT_TEMPLATE = "default"; +$Conf::DEFAULT_TEMPLATE = "default"; # name of the default template ############################ ## DATABASE CONFIGURATION ## ############################ -$DB_TYPE = "mysql"; +$Conf::DB_TYPE = "mysql"; # dbi database type (only MySQL is # supported currently, due to the # fact that "LIMIT X,X", and "RAND()" # is used -$DB_NAME = "k121598_kwotes"; +$Conf::DB_NAME = "kwotes"; # database name -$DB_HOST = "mysql4-k"; +$Conf::DB_HOST = "localhost"; # database host -$DB_USER = "k121598rw"; +$Conf::DB_USER = "root"; # database user -$DB_PASS = "kw0t3s"; +$Conf::DB_PASS = "bejane"; # database password ############################ ## GENERAL STUFF ## ############################ -$SECS_BETWEEN_KWOTES = 60*60; +$Conf::CAPTCHA_SALT = "Kw0t3zCapTchASal7"; +# The "Salt" to add to the captcha +# md5s that are sent to the user, +# It's a good idea to change this + +$Conf::SECS_BETWEEN_KWOTES = 60*60; # seconds a user must wait after # submitting MAX_KWOTES_PER_IP # kwotes to the system before they # are allowed to submit another # kwote -$KWOTE_DEATH_RATING = -1; +$Conf::KWOTE_DEATH_RATING = -1; # lowest rating a quote can be # before it's deleted. A kwote is # only deleted if it's been this # number (or lower) for longer than # the KWOTE_TTL -$KWOTE_TTL = (60*60)*24; +$Conf::MAX_KWOTES_PER_IP = 5; +# maximum kwotes allowed per ip +# in SECS_BETWEEN_KWOTES + +$Conf::KWOTE_TTL = (60*60)*24; # seconds before a "dead" # quote is moved to the kwote # backup table and deleted -$VOTE_TTL = (60*60)*24; -# seconds a vote log lasts, the vote -# log is the mechanism that keeps -# people from voting over and over - -$MAX_VOTES_PER_IP = 4; +$Conf::MAX_VOTES_PER_IP = 4; # maximum votes per ip address per # VOTE_TTL seconds. -$MAX_KWOTES_PER_IP = 5; -# maximum kwotes allowed per ip -# in SECS_BETWEEN_KWOTES - +$Conf::SECS_BETWEEN_VOTES = 60*60; +# seconds a user must wait after +# submiting MAX_VOTES_PER_IP +# votes to a single kwote before +# they are allowed to submit +# another vote for it 1; diff --git a/kwotes.pl b/kwotes.pl index 6353392..b9b5678 100755 --- a/kwotes.pl +++ b/kwotes.pl @@ -15,22 +15,23 @@ # bring in the required libs require "kwotes-lib.pl"; -# bring in the config -require "kwotes.conf.pl"; +# we're strict +package Main; +use strict; # is this getting called by the "delete" cronjob? if ($ARGV[0] eq "cleanup") { - exit cleanup(); + exit Lib::cleanup(); } # parse the form data -my %FORM = parse_form(); +my %FORM = Lib::parse_form(); # some vars my $action = $FORM{"action"}; my $main_content; my %vars; -my $template = ($FORM{"template"}) ? $FORM{"template"} : $DEFAULT_TEMPLATE; +my $template = ($FORM{"template"}) ? $FORM{"template"} : $Conf::DEFAULT_TEMPLATE; # populate %vars with ENV foreach my $key (keys %ENV) { @@ -38,47 +39,54 @@ foreach my $key (keys %ENV) { } # add information that can be displayed on every page -$vars{KWOTE_COUNT} = get_kwote_count(); -$vars{KWOTE_BACKUP_COUNT} = get_kwote_backup_count(); -$vars{SITE_NAME} = $SITE_NAME; -$vars{TAG_LINE} = get_tagline(); +$vars{KWOTE_COUNT} = Lib::get_kwote_count(); +$vars{KWOTE_BACKUP_COUNT} = Lib::get_kwote_backup_count(); +$vars{SITE_NAME} = $Conf::SITE_NAME; +$vars{TAG_LINE} = Lib::get_tagline(); $vars{TEMPLATE_DIR} = "templates/$template"; -# send header -print get_template_headers($template)."\n\n"; - ############ # action: add (show add form) if ($action eq "add") { $vars{TITLE} = "Add Kwote"; - $main_content = wrap_template($template, $CONTENT_ADD, %vars); + $vars{CAPTCHA_ID} = Lib::gen_captcha_phrase(); + $vars{KWOTE_TEXT} = ""; + $main_content = Lib::wrap_template($template, $Lib::CONTENT_ADD, %vars); ############ # action: doadd (add the kwote to the db) } elsif ($action eq "doadd") { - if ($FORM{"content"} eq "") { + # check the captcha + if (!Lib::validate_captcha($FORM{"cid"}, $FORM{"phrase"})) { + $vars{TITLE} = "Add Kwote"; + $vars{ERROR_MESSAGE} = "Captcha validation failed"; + $vars{CAPTCHA_ID} = Lib::gen_captcha_phrase(); + $vars{KWOTE_TEXT} = $FORM{"content"}; + $main_content = Lib::wrap_template($template, $Lib::CONTENT_ADD, %vars); + + } elsif ($FORM{"content"} eq "") { $vars{TITLE} = "An Error Occured"; $vars{ERROR_MESSAGE} = "No text entered"; - $main_content = wrap_template($template, $CONTENT_ERROR, %vars); + $main_content = Lib::wrap_template($template, $Lib::CONTENT_ERROR, %vars); } else { # add the kwote - my $dbh = get_db_connection(); - my $kid = add_kwote($dbh, $FORM{"content"}, $ENV{"REMOTE_ADDR"}); + my $dbh = Lib::get_db_connection(); + my $kid = Lib::add_kwote($dbh, $FORM{"content"}, $ENV{"REMOTE_ADDR"}); # wtf? errors? in my code? noooo. if (!defined($kid)) { $vars{TITLE} = "An Error Occured"; $vars{ERROR_MESSAGE} = "Couldn't add kwote: ".$DBI::errstr; - $main_content = wrap_template($template, $CONTENT_ERROR, %vars); + $main_content = Lib::wrap_template($template, $Lib::CONTENT_ERROR, %vars); # all was good } else { $vars{TITLE} = "Kwote Added"; $vars{KWOTE_ID} = $kid; - $main_content = wrap_template($template, $CONTENT_ADD_THANKS, %vars); + $main_content = Lib::wrap_template($template, $Lib::CONTENT_ADD_THANKS, %vars); } } @@ -88,24 +96,24 @@ if ($action eq "add") { } elsif ($action eq "show") { # get the kwote - my $dbh = get_db_connection(); - my $kwote = get_kwote($dbh, $FORM{"id"}); + my $dbh = Lib::get_db_connection(); + my $kwote = Lib::get_kwote($dbh, $FORM{"id"}); # wtf? errors? in my code? noooo. if (!defined($kwote)) { $vars{TITLE} = "Kwote Does Not Exist"; $vars{ERROR_MESSAGE} = "That kwote does not exist"; - $main_content = wrap_template($template, $CONTENT_ERROR, %vars); + $main_content = Lib::wrap_template($template, $Lib::CONTENT_ERROR, %vars); # all was good } else { $vars{TITLE} = "Kwote \#$kwote->{'id'}"; $vars{KWOTE_ID} = $kwote->{'id'}; - $vars{KWOTE_TEXT_HTML} = html_escape($kwote->{'content'}); - $vars{KWOTE_TEXT_XML} = xml_escape($kwote->{'content'}); + $vars{KWOTE_TEXT_HTML} = Lib::html_escape($kwote->{'content'}); + $vars{KWOTE_TEXT_XML} = Lib::xml_escape($kwote->{'content'}); $vars{KWOTE_TEXT_PLAIN} = $kwote->{'content'}; $vars{KWOTE_RATING} = $kwote->{'rating'}; - $main_content = wrap_template($template, $KWOTE_EVEN, %vars); + $main_content = Lib::wrap_template($template, $Lib::KWOTE_EVEN, %vars); } @@ -143,8 +151,8 @@ if ($action eq "add") { my $min_rating = $FORM{"minr"}; # get the kwote - my $dbh = get_db_connection(); - my @rows = list_kwotes( + my $dbh = Lib::get_db_connection(); + my @rows = Lib::list_kwotes( $dbh, $sort, $sort_order, @@ -172,74 +180,81 @@ if ($action eq "add") { # forward, no back if ($FORM{"o"} ne "random" && $start_index<=0 && @rows>=$max_returned && ($start_index+$max_returned)<$max_records) { - $navigation_template = $NAVIGATION_NO_BACK; + $navigation_template = $Lib::NAVIGATION_NO_BACK; # forward and back } elsif ($FORM{"o"} ne "random" && $start_index>0 && @rows>=$max_returned && ($start_index+$max_returned)<$max_records ) { - $navigation_template = $NAVIGATION; + $navigation_template = $Lib::NAVIGATION; # back only } elsif ($FORM{"o"} ne "random" && $start_index>0 && @rows<$max_returned) { - $navigation_template = $NAVIGATION_NO_FORWARD; + $navigation_template = $Lib::NAVIGATION_NO_FORWARD; } # wrap the navigation template - $main_content .= wrap_template($template, $navigation_template, %vars); + $main_content .= Lib::wrap_template($template, $navigation_template, %vars); # wrap up the "before list" template - $main_content .= wrap_template($template, $BEFORE_LIST, %vars); + $main_content .= Lib::wrap_template($template, $Lib::BEFORE_LIST, %vars); # loop through the results if (defined(@rows)) { for (my $i=0; $i<@rows && ($i+$start_index)<$max_records; $i++) { my $row = $rows[$i]; - my $kwote_template = (($i % 2) != 0) ? $KWOTE_ODD : $KWOTE_EVEN; + my $kwote_template = (($i % 2) != 0) ? $Lib::KWOTE_ODD : $Lib::KWOTE_EVEN; $vars{KWOTE_ID} = $row->{'id'}; - $vars{KWOTE_TEXT_HTML} = html_escape($row->{'content'}); - $vars{KWOTE_TEXT_XML} = xml_escape($row->{'content'}); + $vars{KWOTE_TEXT_HTML} = Lib::html_escape($row->{'content'}); + $vars{KWOTE_TEXT_XML} = Lib::xml_escape($row->{'content'}); $vars{KWOTE_TEXT_PLAIN} = $row->{'content'}; $vars{KWOTE_RATING} = $row->{'rating'}; - $main_content .= wrap_template($template, $kwote_template, %vars); + $main_content .= Lib::wrap_template($template, $kwote_template, %vars); } } # wrap up the "after list" template - $main_content .= wrap_template($template, $AFTER_LIST, %vars); + $main_content .= Lib::wrap_template($template, $Lib::AFTER_LIST, %vars); # wrap the navigation template - $main_content .= wrap_template($template, $navigation_template, %vars); + $main_content .= Lib::wrap_template($template, $navigation_template, %vars); ########## # action: search (show the search page) } elsif ($action eq "search") { $vars{TITLE} = "Search"; - $main_content = wrap_template($template, $CONTENT_SEARCH, %vars); + $main_content = Lib::wrap_template($template, $Lib::CONTENT_SEARCH, %vars); ########## # action: love } elsif ($action eq "love") { - vote($ENV{"REMOTE_ADDR"}, $FORM{"kid"}, "1"); + Lib::vote($ENV{"REMOTE_ADDR"}, $FORM{"kid"}, "1"); $vars{TITLE} = "Love"; $main_content = "Vote Counted"; ########## # action: hate } elsif ($action eq "hate") { - vote($ENV{"REMOTE_ADDR"}, $FORM{"kid"}, "-1"); + Lib::vote($ENV{"REMOTE_ADDR"}, $FORM{"kid"}, "-1"); $vars{TITLE} = "Hate"; $main_content = "Vote Counted"; +########## +# action: captcha +} elsif ($action eq "captcha") { + Lib::serve_captcha($FORM{'cid'}); + exit; + ########## # show the homepage } else { $vars{TITLE} = "The Better kwote Database"; - $main_content = wrap_template($template, $CONTENT_DEFAULT, %vars); + $main_content = Lib::wrap_template($template, $Lib::CONTENT_DEFAULT, %vars); } -# finish the HTML -render_template($template, $HEADER, %vars); +# send the HTML +print Lib::get_template_headers($template)."\n\n"; +Lib::render_template($template, $Lib::HEADER, %vars); print STDOUT $main_content; -render_template($template, $FOOTER, %vars); +Lib::render_template($template, $Lib::FOOTER, %vars); diff --git a/kwotes.sql b/kwotes.sql index 5e11b70..036d9fb 100755 --- a/kwotes.sql +++ b/kwotes.sql @@ -19,10 +19,16 @@ CREATE TABLE kwote_backup ( CREATE TABLE vote ( id INT AUTO_INCREMENT, - ip_address VARCHAR(15), kwote_id INT, + vote INT, + ip_address VARCHAR(15), vote_dt DATETIME, - PRIMARY KEY(id), - FOREIGN KEY(kwote_id) REFERENCES kwote(id) + PRIMARY KEY(id) +); + +CREATE TABLE captchas ( + id INT AUTO_INCREMENT, + phrase VARCHAR(255), + PRIMARY KEY(id) ); diff --git a/templates/default/add-kwote b/templates/default/add-kwote index 0d945c1..c7e55fe 100755 --- a/templates/default/add-kwote +++ b/templates/default/add-kwote @@ -1,9 +1,20 @@ 
- + +
+ + + + + +   + Enter the letters you see to the left: + + + diff --git a/templates/default/header b/templates/default/header index b8b4c58..66d66e5 100755 --- a/templates/default/header +++ b/templates/default/header @@ -52,7 +52,7 @@
- Kwote #  + Kwote #