Made all scripts "use strict"

Implemented Captcha
This commit is contained in:
briandilley 2006-10-23 22:14:15 +00:00
parent ab68bd0d6c
commit eed35515bf
6 changed files with 281 additions and 115 deletions

View File

@ -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)<?"
);
$sth->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("",<IN>);
close(IN);
return $data;
}
##
@ -364,7 +488,7 @@ sub wrap_template {
open(IN,"templates/$template/$template_file");
my $data = join("",<IN>);
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/+/ /;

View File

@ -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;

105
kwotes.pl
View File

@ -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);

View File

@ -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)
);

View File

@ -1,9 +1,20 @@
 <form action="${SCRIPT_NAME}" method="post">
<div style="margin: 5px;">
<input type="hidden" name="action" value="doadd" />
<textarea cols="80" rows="20" name="content" style="width: 100%;"></textarea>
<input type="hidden" name="cid" value="${CAPTCHA_ID}" />
<textarea cols="80" rows="20" name="content" style="width: 100%;">${KWOTE_TEXT}</textarea>
<br />
<span style="float: left;">
<img src="${SCRIPT_NAME}?action=captcha&amp;cid=${CAPTCHA_ID}" width="120" height="30" border="0" />
</span>
<span style="float: left;">
&nbsp;
Enter the letters you see to the left:
<input type="text" name="phrase" />
</span>
<span style="float: right;">
<input type="submit" value="Submit Quote" />
</span>

View File

@ -52,7 +52,7 @@
<form id="searchbox" action="${SCRIPT_NAME}" method="get">
<div>
<input type="hidden" name="action" value="show" />
Kwote #&nbsp;<input type="text" size="5" name="kwoteid" id="kwoteid" />
Kwote #&nbsp;<input type="text" size="5" name="id" id="kwoteid" />
</div>
</form>