(1) For example, not too well documented:
use strict;
use CGI::Pretty qw(-nosticky);
use HTML::Entities;
use DBI;
$|++;
#
# IsMyCodeHotOrNot.pl
#
# Kwok-Bun Yue February 23, 2001
#
# This CGI program accepts submission of
code by users and lets
# users vote on the degree of hotness of
each code. This is
# a toy program modeled after the site AmIHotOrNot.com,
except
# that program code, not pictures are hosted.
#
# There are no error checking for the submitted
form.
#
=pod MS Access Table:
IsMyCodeHotOrNot
Pid AutoNumber
name Text(50)
email Text(100)
description Text(255)
title Text(200)
code Memo
when Date/Time
=cut
# Porting Global constants.
# Stylesheet file.
my $STYLE_FILE = 'styles/IsMyCodeHotOrNot.css';
# ODBC DSN
my $DSN = 'yuep';
# Voting range.
my $MIN_VOTE = 1;
my $MAX_VOTE = 10;
# Global constatns for author information.
my $AUTHOR_EMAIL = 'yue@uhcl.edu';
my $COPYRIGHT = 'copyright 2001 Kwok-Bun
Yue';
# Global CGI object.
my $q = new CGI::Pretty;
# This file name without path.
my $SELF = $q->script_name();
# Remove path.
if ($SELF =~ /([^\\\/]*)$/) {
$SELF = $1;
}
# Remove query string.
$SELF =~ s/\?.*//;
# Name of the hidden HTTP parameter for storing
which page
# the request comes from and
which page to go to.
my $FROM = 'from';
my $TO = 'to';
# Values of the $FROM and $TO HTTP parameters.
my $VOTING_PAGE = 'votingPage';
my $SUBMIT_FORM = 'submitForm';
my $SUCCESSFUL_SUBMISSION = 'successfulSubmission';
# HTTP parameter for form voting.
my $VOTE = "vote";
# HTTP parameter for the unique id identifying
# the code stored in the database.
my $PID = "pid";
# HTTP parameters for form submissions.
my $NAME ='name';
my $DESCRIPTION = 'description';
my $EMAIL = 'email';
my $TITLE = 'title';
my $CODE = 'code';
my $CODEFILE = 'codefile';
my $LANGUAGE = 'language';
# Get HTTP parameters.
my $from = $q->param($FROM);
my $to = $q->param($TO);
my $name = $q->param($NAME);
my $email = $q->param($EMAIL);
my $description = $q->param($DESCRIPTION);
my $title = $q->param($TITLE);
my $language = $q->param($LANGUAGE);
my $code = $q->param($CODE);
my $codefile = $q->param($CODEFILE);
my $pid = $q->param($PID);
my $vote = $q->param($VOTE);
# Main logic
if (!$to || $to eq $VOTING_PAGE) {
my $dbh = DBI->connect("dbi:ODBC:$DSN");
displayVotingPageHeader();
# Display Main page:
if ($pid || $vote) {
print $q->a({href=>"$SELF?$TO=$SUBMIT_FORM"},'Submit
your own code'),
$q->p;
# Store vote and display result.
exit 0 unless saveVoteToDb($pid, $vote,$dbh);
displayVotingResult($pid, $vote, $dbh);
}
else {
displayWelcomeMessage();
}
unless (displayNextCodeForVoting($pid,$dbh))
{
print "Sorry, no code yet. You
are the first visitor. Please submit code.",
$q->p;
displaySubmissionForm();
}
displayVotingPageFooter();
$dbh->disconnect;
}
else {
if ($to eq $SUBMIT_FORM) {
displaySubmissionPageHeader();
displaySubmissionForm();
displaySubmissionPageFooter();
}
else {
if ($to eq $SUCCESSFUL_SUBMISSION)
{
exit 0 unless saveSubmissionToDb($name,
$email, $description, $title, $language, $code, $codefile);
displaySubmissionAcknowledgement();
}
else {
# Error.
displayErrorPage('An unknown
error has occurred. Please look for future version.');
}
}
}
exit 0; # main.
# Display the header of the voting page.
sub displayVotingPageHeader {
print $q->header,
$q->start_html(-title=>'Submission
Form for IsMyCodeHotOrNot',
-author=>$AUTHOR_EMAIL,
-meta=>{'keywords'=>'program code survey',
'copyright'=>$COPYRIGHT},
-style=>{'src'=>$STYLE_FILE}),
$q->h2('Is my code hot
or not?'),
} # displayVotingPageHeader
# Save the vote to the database.
sub saveVoteToDb {
my ($pid,$vote,$dbh) = @_;
return unless $pid && $vote;
my $votecount = 1; # Number of count
for the vote.
my $sql = "select votecount
from IsMyCodeHotOrNotVote " .
"where pid = $pid
and vote = $vote";
# debug: print $q->header, "SQL
=> $sql<p>";
my $sth = $dbh->prepare($sql) || die
$q->header . $dbh->errstr;
$sth->execute();
# Check whether someone has voted for
the pid with
# the same vote before.
if (my @row = $sth->fetchrow_array)
{
# Vote already exists. Increment
the count.
$votecount = $row[0] + 1;
$sql = "update IsMyCodeHotOrNotVote
" .
"set votecount
= $votecount " .
"where pid
= $pid and vote = $vote";
}
else {
$sql = "insert into IsMyCodeHotOrNotVote(pid,
vote, votecount) " .
"values($pid,
$vote, $votecount)";
}
# debug: print $q->header, "SQL =>
$sql<p>";
$sth = $dbh->prepare($sql) || die $q->header
. $dbh->errstr;
$sth->execute();
} # saveVoteToDb
# display the voting result. The current
code does not handle the
# case where there is no voting.
sub displayVotingResult {
my $averageVote = 0;
my $numVote = 0;
my ($pid, $vote, $dbh) = @_;
# Get total number of votes.
my $sql = "select sum(votecount)
from IsMyCodeHotOrNotVote " .
"where pid = $pid
" .
"group by pid";
# debug: print $q->header, "SQL
=> $sql<p>";
my $sth = $dbh->prepare($sql);
$sth->execute();
if (my @row = $sth->fetchrow_array)
{
# Vote already exists. Increment
the count.
$numVote = $row[0];
}
# Get average number of votes.
if ($numVote) {
$sql = "select sum(vote*votecount)/sum(votecount)
from IsMyCodeHotOrNotVote " .
"where pid
= $pid " .
"group by
pid";
# debug: print $q->header,
"SQL => $sql<p>";
my $sth = $dbh->prepare($sql);
$sth->execute();
if (my @row = $sth->fetchrow_array)
{
# Vote already exists.
Increment the count.
$averageVote = $row[0];
}
}
$sql = "select name, title, language
from IsMyCodeHotOrNot " .
"where pid = $pid";
$sth = $dbh->prepare($sql);
$sth->execute();
my ($name, $title, $language) = undef;
if (my @row = $sth->fetchrow_array)
{
# Vote already exists. Increment
the count.
($name, $title, $language) = @row;
}
print 'For the ',
$q->span({-class=>'lightEmp'},
$language),
' program titled ',
$q->span({-class=>'lightEmp'},
$title),
' written by ',
$q->span({-class=>'person'},
$name),
':',
$q->p,
"Your rating on the program:
$vote.",
$q->br,
'Total number of votes:
' , int($numVote), '.',
$q->br,
'Average rating: ', sprintf("%-.2f",
$averageVote), '.',
$q->p;
} # displayVotingResult
# Display the next code for voting.
sub displayNextCodeForVoting {
my ($currentPid,$dbh) = @_;
my $nextPid = 0;
my $sql = '';
my $sth = undef;
# Get the next Pid to be displayed.
if ($currentPid) {
$sql = "select max(pid)
from IsMyCodeHotOrNot " .
"where pid
< $currentPid ";
# debug: print $q->header,
"SQL => $sql<p>";
$sth = $dbh->prepare($sql);
$sth->execute();
if (my @row = $sth->fetchrow_array)
{
$nextPid = $row[0];
}
}
unless ($nextPid) {
$sql = "select max(pid) from IsMyCodeHotOrNot
";
$sth = $dbh->prepare($sql);
$sth->execute();
if (my @row = $sth->fetchrow_array)
{
$nextPid = $row[0];
}
}
# The table is empty.
return 0 unless $nextPid;
# display the result.
print $q->h3('Please give your vote
for the following code'),
$q->p;
# Print voting choices as links.
print '(NOT) ';
for (my $i=$MIN_VOTE; $i <= $MAX_VOTE;
$i++) {
print $q->a({href=>"$SELF?$TO=$VOTING_PAGE&$PID=$nextPid&$VOTE=$i"},$i),
' ';
}
print '(HOT)';
# Print the code:
print $q->p;
$sql = "select name, email, title, language,
description, code, when from IsMyCodeHotOrNot " .
"where pid = $nextPid";
$sth = $dbh->prepare($sql);
$sth->{LongReadLen} = 1000000; # Set
large buffer to read memo.
$sth->execute();
my ($name, $email, $title, $language,
$description, $code, $when) = undef;
if (my @row = $sth->fetchrow_array)
{
# Vote already exists. Increment
the count.
($name, $email, $title, $language,
$description, $code, $when) = @row;
}
$code =~ s/ / /g;
print $q->span({-class=>'lightEmp'},
$language),
' program submitted by
',
$q->span({-class=>'person'},
$name),
' at ',
$q->a({href=>"mailto:$email"},$email),
" on $when:",
$q->p,
$q->span({-class=>'lightEmp'},
'Title:'),
$title,
$q->p,
$q->span({-class=>'lightEmp'},
'Description:'),
$q->p,
$description,
$q->p,
$q->span({-class=>'lightEmp'},
'Code:'),
$q->p,
$q->div({-class=>'code'},
$code);
1;
} # displayNextCodeForVoting
# print the footer of the voting page.
sub displayVotingPageFooter {
print end_html;
}
# Display initial welcome messgae.
sub displayWelcomeMessage {
print 'Welcome to "Is My Code Hot or
not?" ',
'In
this page, you can vote for the hotness of ',
'other people code or
you can ',
$q->a({href=>"$SELF?$TO=$SUBMIT_FORM"},'submit
your own code'),
' and let other people
to vote on it.',
$q->p;
} # displayWelcomeMessage
# Display the submission
page header.
sub displaySubmissionPageHeader {
print $q->header,
$q->start_html(-title=>'Submission
Form for IsMyCodeHotOrNot',
-author=>$AUTHOR_EMAIL,
-meta=>{'keywords'=>'program code survey',
'copyright'=>$COPYRIGHT},
-style=>{'src'=>$STYLE_FILE}),
$q->h2('Is my code hot
or not?'),
$q->h4('Submit your code
here'),
$q->p;
} # displaySubmissionPageHeade
# Display the form for accepting
code submission.
sub displaySubmissionForm {
# This is added because CGI.pm 'nosticky'
pragma does
# not appy to hidden field. It
is necessary to change
# it explicitly.
$q->param($TO, $SUCCESSFUL_SUBMISSION);
print $q->start_multipart_form(-action=>$SELF),
# $q->hidden(-name=>$FROM,
#
-default=>[$SUBMIT_FORM]),
$q->hidden(-name=>$TO,
-default=>[$SUCCESSFUL_SUBMISSION]),
'Your name: ',
$q->textfield(-name=>$NAME,
-size=>20,
-maxlength=>50),
$q->br,
'Email address: ',
$q->textfield(-name=>$EMAIL,
-size=>30,
-maxlength=>80),
$q->br,
'Code title: ',
$q->textfield(-name=>$TITLE,
-size=>40,
-maxlength=>120),
$q->p,
'Code description:',
$q->br,
$q->textarea(-name=>$DESCRIPTION,
-rows=>5,
-columns=>50),
$q->p,
'Language of the code:
',
$q->scrolling_list(-name=>$LANGUAGE,
-values=>['Perl','Java','C','Visual Basic'],
-size=>1),
$q->p,
'Upload your code file:
',
$q->filefield(-name=>$CODEFILE,
-size=>30,
-maxlength=>80),
$q->br,
'Or cut and paste your
code below: ',
$q->br,
$q->textarea(-name=>$CODE,
-rows=>5,
-columns=>50),
$q->p,
$q->submit(-name=>'submit',
-value=>'Submit Code!'),
' ',
$q->reset,
$q->endform;
$q->end_html;
} # displaySubmissionForm
# Display the submission
page footer.
sub displaySubmissionPageFooter {
print $q->end_html;
} # displaySubmissionPageFooterer
# Display an acknowledgement page that the
submission
# has been successful.
sub displaySubmissionAcknowledgement {
print $q->header,
$q->start_html(-title=>'Submission
Result for IsMyCodeHotOrNot',
-author=>$AUTHOR_EMAIL,
-meta=>{'keywords'=>'program code survey',
'copyright'=>$COPYRIGHT},
-style=>{'src'=>$STYLE_FILE}),
$q->h2('Your submission
is successful'),
$q->h4('Thank you for
your code submission'),
'You may go to the ',
$q->a({href=>"$SELF?$TO=$VOTING_PAGE"},'voting'),
' page.',
$q->end_html;
} # displaySubmissionAcknowledgement
# Save the submission to the database.
sub saveSubmissionToDb {
my ($name, $email, $description, $title,
$language, $code, $codefile) = @_;
# If there is a non-empty uploaded file,
use it instead of the code
# from the text area.
if ($codefile) {
my $tempCode = '';
my $fh = $q->upload($CODEFILE);
if ($fh) {
while (<$fh>) {
$tempCode .= $_;
}
}
$code = $tempCode? $tempCode : $code;
}
# Insert the submission.
$name = HTML::Entities::decode($name);
$email = HTML::Entities::decode($email);
$description = HTML::Entities::decode($description);
$title = HTML::Entities::decode($title);
$language = HTML::Entities::decode($language);
$code = HTML::Entities::decode($code);
# Change ' to two 's
$name =~ s/'/''/g;
$email =~ s/'/''/g;
$description =~ s/'/''/g;
$title =~ s/'/''/g;
$language =~ s/'/''/g;
# Add <br>.
$code =~ s/\n/<br>/sg;
my $dbh = DBI->connect("dbi:ODBC:$DSN");
my $sql = "insert into
IsMyCodeHotOrNot(name,email,description,title,language,code,when) " .
"values('$name','$email','$description', '$title', '$language', ?, Now())";
# debug: print $q->header,
"SQL => $sql<p>";
my $sth = $dbh->prepare($sql);
$sth->bind_param(1, $code, DBI::SQL_LONGVARCHAR);
unless ($sth->execute()) {
displayErrorPage('An DB error has
occured. Please consult the administrator.' .
$dbh->errstr);
return 0;
}
$dbh->disconnect;
1;
}
# Error Page that should never be displayed.
sub displayErrorPage {
my $message = shift;
print $q->header,
$q->start_html(-title=>'Error
Page for IsMyCodeHotOrNot',
-author=>$AUTHOR_EMAIL,
-meta=>{'keywords'=>'program code survey',
'copyright'=>$COPYRIGHT},
-style=>{'src'=>$STYLE_FILE}),
$q->h2('Is Your Code Hot
Or Not: Error Page'),
$q->h4($message),
$q->end_html;
} # displayErrorPage
IsMyCodeHotOrNot.css:
body, table, tr, td, input, textarea, select
{font-size:10pt; font-family:verdana;}
h1, h2, h3, h4, h5, h6 {font-family:verdana;}
body {background-color:#ccccff;}
A:link {color:#80000;
font-size:10pt; text-decoration:none;}
A:visited {color:#008000; font-size:10pt;
text-decoration:none;}
A:active {color:#000080; font-size:10pt;
text-decoration:none;}
A:hover {color:#c00000; font size:10pt;
text-decoration:none; font-weight:bold;}
.lightEmp {color:red}
.person {color:blue}
.code {background-color:#ffffff; font-family:Arial;
font-size:9pt;}