📄 ch17.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 17 -- Voting Booths </TITLE>
<META>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 17</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Voting Booths</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#VotingBoothsGatheringandManagingOpi" >Voting Booths-Gathering and Managing Opinions</A>
<LI><A HREF="#StartingSimpleALowLevelVotingBooth" >Starting Simple-A Low-Level Voting Booth</A>
<LI><A HREF="#BadVotingBoothGoodCodeTechnicalMe" >Bad Voting Booth, Good Code-Technical Merits of greenegg.cgi</A>
<UL>
<LI><A HREF="#UseofAssociativeArraysfortheHandli" >Use of Associative Arrays for the Handling of GET/POST Method Data</A>
<LI><A HREF="#ImmediateErrorTrappingUsingtheState" >Immediate Error Trapping Using the Statement Modifier Form of if</A>
<LI><A HREF="#SlurpingDatawitharrayFILEHANDLE" >Slurping Data with @array = <FILEHANDLE>;</A>
<LI><A HREF="#UseofOutputFiltertoProvidestdinto" >Use of Output Filter to Provide stdin to /usr/sbin/sendmail and sendmail -t Flag</A>
<LI><A HREF="#UseofprintFHENDENDSyntaxWhe" >Use of print FH<<END; ... END Syntax When Outputting Formatted Sections</A>
</UL>
<LI><A HREF="#AVotingBoothWishList" >A Voting Booth Wish List</A>
<LI><A HREF="#MultistateCGIProgramsMoreThanJusta" >Multistate CGI Programs-More Than Just a URL</A>
<LI><A HREF="#GeneratingMeaningfulReports" >Generating Meaningful Reports</A>
<UL>
<LI><A HREF="#SortingListsinPerl" >Sorting Lists in Perl</A>
<LI><A HREF="#AverageandStandardDeviationStatistic" >Average and Standard Deviation-Statistics 101</A>
<LI><A HREF="#VisualOutputCreatingGraphs" >Visual Output-Creating Graphs</A>
<LI><A HREF="#HandlingDataInternallyandExternally" >Handling Data Internally and Externally</A>
</UL>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
While there is no special technical distinction to gathering information
in a "voting booth" style, voting booths are used quite
often on the Web. A large part of this popularity is due to the
social familiarity with surveys, polling, and voting. Also, the
structure of a voting booth lends itself well to the technology
of forms. The measure of a voting booth is more a function of
the database back end than the complexity of the form that creates
the data. This chapter presents examples of simple and complicated
voting booth CGI programs.
<H2><A NAME="VotingBoothsGatheringandManagingOpi"><FONT SIZE=5 COLOR=#FF0000>Voting
Booths-Gathering and Managing Opinions</FONT></A></H2>
<P>
Since the Web began, people have been using it to gather information.
An interesting turn-around can be engineered with CGI programming:
Web pages can use people to gather information. There are many
different strategies on how to accomplish this: the soliciting
of orders, the active tracking of users, and the creation of threaded
discussion areas are a few examples you'll find in this book.
In addition to these methods, a very popular scheme for gathering
information from users is the <I>voting booth</I>.
<P>
The concept of a voting booth should be intuitively obvious, but
at the same time the words "intuitively obvious" seem
like the computer-industry platitude equivalent to "at least
you still have your health." With this in mind, I'll take
a second to describe the procedure of on-line voting:
<OL>
<LI>A user loads an HTML page with a form area.
<LI>The user answers questions posed by the form.
<LI>The user submits the form through either a SUBMIT button or
an Imagebutton.
<LI>The form data is sent to a CGI program for parsing and processing.
<LI>Reports based on the submitted data are generated. These reports
could be in the form of dynamically generated Web pages, e-mail,
server-based data files, images created on-the-fly, and so on.
</OL>
<P>
This sequence of actions should be very familiar to anyone who
has a moderate degree of Web experience. The problem is that this
sequence isn't unique; these steps could equally well describe
a shopping cart or other sorts of order entry, too. On one level,
there is no essential difference between a voting booth and these
sorts of CGI applications. This is due to the structure imposed
on users by forms and the client-server model of the Web. So long
as forms control the ways HTML programmers can ask users for input,
the <TT><FONT FACE="Courier">GET</FONT></TT>/<TT><FONT FACE="Courier">POST</FONT></TT>
methods circumscribe the data encoding format, and permanent information
must be stored and organized server-side, we aren't likely to
see a revolution in how CGI programming is performed. Still, there
is a special "feel" to surveys, voting booths, and polling
stations that deserves in-depth analysis.
<H2><A NAME="StartingSimpleALowLevelVotingBooth"><FONT SIZE=5 COLOR=#FF0000>Starting
Simple-A Low-Level Voting Booth</FONT></A></H2>
<P>
Though obvious, it must be stated that there are both good and
bad voting booths on the Web. I think the difference between the
two is
<UL>
<LI><FONT COLOR=#000000>The quality of the report generated by
the CGI program</FONT>
<LI><FONT COLOR=#000000>The degree of data management capability
the voter and administrator have over the votes</FONT>
</UL>
<P>
To start this discussion, I've created an example of a reasonably
simple voting booth, as shown in Listing 17.1. You can find this
example on-line at
<BLOCKQUOTE>
<TT><FONT FACE="Courier"><A HREF="http://www.anadas.com/cgiunleashed/voting/greenegg.html">http://www.anadas.com/cgiunleashed/voting/greenegg.html</A></FONT></TT>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 17.1. greenegg.html-The HTML half of a simple voting
booth system.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"><HTML><BR>
<HEAD><TITLE>Are green eggs and ham meant for you?</TITLE></HEAD>
<BR>
<BODY><BR>
<H2>Funny Foods Grillhouse Customer Survey</H2><BR>
<P><BR>
Funny Foods is conducting a survey of our restaurent goers to
test the<BR>
marketability of a new main course we're planning.<BR>
<P><BR>
<FORM METHOD=GET ACTION=exe/greenegg.cgi><BR>
Do you like green eggs and ham?<BR><BR>
<SELECT SIZE=2 NAME=disposition><BR>
<OPTION SELECTED VALUE="dislike">I do not like
them, Sam I am</OPTION><BR>
<OPTION VALUE="like">Yes, I'll try them, Sam I
am</OPTION><BR>
</SELECT><BR>
<P><BR>
If yes, what is the most you would pay for green eggs and ham
at a<BR>
restaurant?<BR><BR>
<SELECT NAME=pay><BR>
<OPTION SELECTED>[select an amount]</OPTION><BR>
<OPTION>$6</OPTION><BR>
<OPTION>$9</OPTION><BR>
<OPTION>$12</OPTION><BR>
<OPTION>$15</OPTION><BR>
<OPTION>$18</OPTION><BR>
<OPTION>$21</OPTION><BR>
</SELECT><BR>
<P><BR>
<INPUT TYPE=SUBMIT VALUE="Click here when finished">
<BR>
</FORM><BR>
</BODY></HTML></FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
This voting booth isn't particularly good. In my humble, objective,
and removed opinion, it's a fine computer program. However, it
doesn't live up to the two points I made previously. I'll discuss
its technical merits and also examine how a better voting booth
could be constructed. For your viewing delight, and to save you
from booting up your browser, I've provided you with a screen
shot of my simple voting booth page in Figure 17.1.
<P>
<A HREF="f17-1.gif" ><B>Figure 17.1 : </B><I>The entry page of my simple voting booth</I></A><I>.</I>
<HR>
<BLOCKQUOTE>
<B>Listing 17.2. greenegg.cgi-A simple voting booth CGI program.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">#!/usr/bin/perl<BR>
<BR>
#<BR>
# The following lines are "initializations" of one sort
or another.<BR>
#<BR>
# Redirecting standard error to /dev/null is handy when dealing
with<BR>
# the 'sendmail' UNIX command since sendmail has an odd habit
of having<BR>
# errors it may encounter being piped to the HTTPd. This
is the only<BR>
# circumstance where I've seen standard out (STDOUT) and standard
error<BR>
# (STDERR) get confused with each other.<BR>
#<BR>
chop($time = 'date');<BR>
$refpage = 'http://www.anadas.com/cgiunleashed/voting/greenegg.html';
<BR>
$admin_email = 'rdice@anadas.com';<BR>
open(STDERR,"> /dev/null");<BR>
<BR>
# -- start of my standard GET/POST method handler --<BR>
#<BR>
# At the end of this section of code, I'll have the %tokens associative
<BR>
# array with the 'name' information from the submitting form as
keys and<BR>
# 'value' information as values. Hex-encoded special
characters will be<BR>
# restored to their original characters. Note that
many browsers will<BR>
# return annoying DOS-style CRLF at line end in textarea boxes. This
<BR>
# code will _not_ strip ^M. If this is desirable, use
<BR>
# $tokens{$field} =~ s/\cM/ /g;<BR>
# $tokens{$field} =~ s/\n//g;<BR>
# as the last lines in the foreach loop.<BR>
#<BR>
<BR>
if ( $ENV{REQUEST_METHOD} eq 'POST' ) {<BR>
read(stdin,$input,$ENV{CONTENT_LENGTH});<BR>
} elsif ( $ENV{REQUEST_METHOD} eq 'GET' ) {<BR>
$input = $ENV{QUERY_STRING};<BR>
} else {<BR>
print "Content-type: text/html\n\n";
<BR>
print "This program doesn't support the
<b>$ENV{REQUEST_METHOD}</b> httpd";<BR>
print " request method.\n";<BR>
exit 1;<BR>
}<BR>
$input =~ tr/+/ /;<BR>
@fields = split(/\&/,$input);<BR>
$input = '';<BR>
foreach $i (@fields) {<BR>
($field,$data) = split(/=/,$i);<BR>
$field =~ s/%(..)/pack("c",hex($1))/ge;
<BR>
$data =~ s/%(..)/pack("c",hex($1))/ge;
<BR>
$tokens{$field} = $data;<BR>
}<BR>
@fields = (); #
delete the @fields array<BR>
<BR>
# -- end of my standard GET/POST method handler --<BR>
<BR>
#<BR>
# The next 3 lines trap errors. The first defuses improper
accesses to<BR>
# greenegg.cgi -- this CGI program -- while the other
two trap for<BR>
# illogical form submissions. The format is:<BR>
# goto subroutine if error condition<BR>
# The various subroutines print to the HTTPd and then abort the
program.<BR>
#<BR>
&refpage_error if $ENV{HTTP_REFERER} ne $refpage;<BR>
&dislike_error if ( ($tokens{'disposition'} eq 'dislike')
&&<BR>
($tokens{'pay'} ne '[select an amount]') );
<BR>
&like_error if ( ($tokens{'disposition'} eq 'like') &&
<BR>
($tokens{'pay'} eq '[select an amount]')
);<BR>
<BR>
#<BR>
# To reach this point, there must be no input errors in the program.
<BR>
# Now, open the database file of historical responses<BR>
#<BR>
open(DB,"greenegg.dat");<BR>
chop(@dataline = <DB>);<BR>
close(DB);<BR>
<BR>
#<BR>
# parse each line, update as appropriate (Didn't like or Liked
and <BR>
# pay amount)<BR>
#<BR>
foreach ( @dataline ) {<BR>
($name,$count) = split(/:\t/);<BR>
if ( (($name eq 'Didn\'t like') && ($tokens{'disposition'}
eq 'dislike'))<BR>
|| (($name eq 'Liked') &&
($tokens{'disposition'} eq 'like'))<BR>
|| ( $tokens{'pay'} eq $name
) ) {<BR>
$count += 1;<BR>
$_ = join(":\t",$name,$count);
<BR>
}<BR>
}<BR>
<BR>
#<BR>
# write new version of data to file<BR>
#<BR>
open(DB,"> greenegg.dat");<BR>
foreach ( @dataline ) {<BR>
print DB "$_\n";<BR>
}<BR>
close(DB);<BR>
chmod 0660, "greenegg.dat";<BR>
<BR>
#<BR>
# Construct a formatted email to send to the administrator of
the Web site.<BR>
# The email is composed of 4 sections: The header (parsed by sendmail),
<BR>
# environment info, info regarding the immediate form submission,
and<BR>
# historical submission info.<BR>
#<BR>
open(EM,"| /usr/sbin/sendmail -t");<BR>
print EM <<END;<BR>
To: $admin_email<BR>
From: "Funny Food Form"<BR>
Subject: Submission of Funny Food Form<BR>
<BR>
The Funny Food Grillhouse Web questionnaire has just received
a submission!<BR>
<BR>
Time of Submission: $time<BR>
Using Browser: $ENV{HTTP_USER_AGENT}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -