\documentclass{article}

%% \usepackage{lgrind}

\setlength{\topmargin}          {-0.5in}
\setlength{\evensidemargin}     {0.25in}
\setlength{\oddsidemargin}      {0.25in}

%%\setlength{\leftmargin} {-0.5in}
\setlength{\textwidth}  {6in}
\setlength{\textheight} {9in}
\newcommand{\ret}{\framebox{\tiny RETURN}}
\newcommand{\ctrld}{\framebox{\tiny Ctrl-D}}
\newcommand{\ctrlc}{\framebox{\tiny Ctrl-C}}

\begin{document}

\begin{center}

{\em Programming in Perl, Fall 97} \\
\underline{Project 2} \\
{\bf Due : Monday, December 8 at midnight} \\
{\bf Weight : } 20\% of course grade \\
Instructor : Louis Ziantz

\end{center}

This assignment will allow you to experiment with creating and running
a CGI script using Perl.  It should be submitted according to the {\em
Submission Guidelines}.  Do not forget to comment your program,
providing a general description of the Perl script and any subroutines
used, along with inline comments for important or complex portions of
code.  Please get started on the assignment as soon as possible.

\section{Motivation}  
A club whose members are distributed across the world elect a
president along with four members of an advisory board every two
years.  Since many of the members have internet access, they would
like to use a simple CGI script to provide the capability of voting
online (and thereby reduce mailing costs).  

\section{Specification}

They would like a single script that both generates a voting form and
processes a user's votes.

\subsection{Form Generation}

Candidates for offices are stored in a file called
\underline{candidates.dat}.  A line of the file has the following format:
\begin{verbatim}
<office>:<last-name>,<first-name>:<vote-count><newline>
\end{verbatim}
where \verb+<office>+ is either \verb+president+ or
\verb+board-member+ and \verb+<vote-count>+ is initially 0.
For example, 
\begin{verbatim}
president:Abbott,Bud:0
president:Costello,Lou:0
board-member:Marx,Groucho:0
board-member:West,Mae:0
\end{verbatim}
You will first need to read and store the names and number of votes in some
reasonable data structures (perhaps one hash for presidential
candidates and another for board candidates).

The \verb+<TITLE>+ of the web page ballot should be \verb+Voting Form+.  
The page itself should consist of the following:

\begin{itemize}

  \item A \verb+<H1>+ heading that reads \verb+Voting Form+.
 
  \item A textfield that allows the user to enter a first name.

  \item A textfield that allows the user to enter a last name.

  \item A textfield that allows the user to enter a membership
  identification number.

  \item A checkbox that asks whether the user just wants the current
  results displayed (instead of voting).

  \item A heading for presidential candidate names, followed by a
  radio group list of candidates on separate lines.  You should only
  be able to vote for one candidate, and no candidate's box should be
  checked at the start.  The candidates names should be printed in
  alphabetical order as \verb+<first-name>+, space,
  \verb+<last-name>+.

  \item A heading for advisory board candidate names are, followed by
  a checkbox group list of candidates on separate lines.  You should
  be able to vote for more than one candidate, but no candidate's box
  should be checked at the start.  The candidates names should be
  printed in alphabetical order as \verb+<first-name>+, space,
  \verb+<last-name>+.

  \item A submit button titled \verb+vote+ and a reset button titled
  \verb+clear+.

\end{itemize}

\subsection{Form Processing}

Before any processing occurs, your code should verify that the user is
a member of the club by making use of a file called
\underline{membership.dat}.  A line of this file has the following
format: 
\begin{verbatim}
<last-name>,<first-name>&<membership-id-number><newline>
\end{verbatim}
For example,
\begin{verbatim}
Fields,W.C.&2348
\end{verbatim}
You should read through the file searching for the membership id
number entered by the user.  If a match is not found, you should
generate a HTML message page that indicates the number was not found in
the membership database.  If a match is found, you should compare the
last name in the file to the last name entered by the user.  If they
are not the same, you should generate another HTML message page that
indicates the number matched, but the name did not.  If both the number
and the last name entered match an entry from the file, the user is
validated and processing should continue; otherwise the script exits.
(Yes, technically, all of the Marx brothers could vote with the same
id, but that is ok.)

After validation, the candidate file must be read as in the form
generation stage.

There are two major options the user can select from the form, based on
the single checkbox that inquires about displaying results.  If the
checkbox is NOT checked, the form should assume that the user is
voting.  If it is checked, the form should simply display the current
state of the election and IGNORE any voting fields set.

\subsubsection{If the user is voting...}

The script should test to make sure that the user voted for no more
than four board members (less than four is fine).  It should generate
an appropriate HTML message page and exit if this occurs.  Otherwise,
the votes are recorded in memory and the candidate file is then
rewritten with the modified vote count in exactly the same form as you
would read in (all candidates should be written out).

An HTML page
consisting of a summary of the user's voting should then be generated.
It should have the \verb+<TITLE>+ \verb+Voting Summary+.  The text
from an example page follows:
\begin{verbatim}
Voting Summary

Thank you Susan Roberts . 
Your votes have been recorded as follows:

President: Lou Costello
Board Selections: 
Mae West
\end{verbatim}
In the above, \verb+Voting Summary+ would be a \verb+<H1>+ heading and
the titles of the offices would be in bold type.


\subsubsection{If the user just wants the current results...}

An HTML page consisting of a summary of the current state of the
election should be generated.  It should have the \verb+<TITLE>+
\verb+Current Results+.  The text from an example page follows:

\begin{verbatim}
Current Results

Votes for President: 

Bud Abbot: 56
Lou Costello: 84

Votes for Advisory Board: 

Groucho Marx: 115
Harpo Marx: 87
Mae West: 123
\end{verbatim}
In the above, \verb+Current Results+ would be a \verb+<H1>+ heading and
the headings for the offices would be \verb+<H3>+.


\section{Details}

\begin{itemize}

  \item Name the script \underline{vote.cgi}.

  \item Include the pragma \verb+use strict;+.

  \item Do not forget to call the appropriate \verb+start_*+ and
  \verb+end_*+ when starting/ending an HTML page or form.

  \item You may assume the initial data files are error free.  I will
  e-mail the class when sample data files are made available on the
  course web page (\verb+http://www.cs.rpi.edu/~ziantzl/perl.html+).

  \item You do not need to write code to prevent the same member from
  voting more than once (the club trusts its members).

  \item You will need to lock \underline{candidates.dat} for
  concurrent read when you read it for input and for exclusive write
  when you modify it.  You can use the code I gave in class.

  \item Make sure you display an HTML error message whenever there is
  an error that you can trap (for example, if a file can't be opened
  or locked).  You can use the \verb+&bail()+ subroutine I gave in
  class or make one of your own.

  \item Make use of subroutines.  The generation and processing of the
  form should be separate subroutines.  The form processing subroutine
  should call at least two other subroutines --- one to display the
  current results and another to record the votes.  Other activities,
  such as reading the candidate file and generating the different HTML
  messages are all candidates for separate subroutines.

  \item Keep the use of global variables to a minimum.  Global
  ``constants'' such as \verb+$LOCK_EX+ are fine.  It is acceptable to
  make the voting data structures global (but you should at least
  experiment with passing a hash or an array by reference, since it
  may be on the exam).

\end{itemize}

\pagebreak

\begin{center}

\underline{Running a CGI Script} \\

\end{center}

\section{CGI.pm}

The CGI Perl Module is available in the directory
\verb+/dept/cs/complang/perl/module+.  You should make a soft link to
it from any directory in which you are going to execute your CGI
script (that is, \verb+ln -s /dept/cs/complang/perl/module/CGI.pm+).  If
you receive the following message from Perl:
\begin{verbatim}
Can't locate CGI.pm in @INC at ./vote.cgi line 7.
BEGIN failed--compilation aborted at ./vote.cgi line 7.
\end{verbatim}
then you don't have access to it from the directory you are in and
need to make the link.  For the purposes of this project, the only
directory you will need to make a link from is
\verb+~/public_html/cgi-bin+ (see {\em Enabling Online CGI Execution}
below) unless you want to do offline testing in another directory.

\section{Offline Execution}

Most of the development of your CGI script should be done in this mode
of execution.  To get offline execution, you simply run the CGI script
as a normal Perl script on, for example, an IBM workstation.  When you
run the script, you will get the following prompt:
\begin{verbatim}
% add.cgi
(offline mode: enter name=value pairs on standard input)
\end{verbatim}

If you hit \ctrld\ at this point, the script should produce the HTML
corresponding to the form that the user will use to enter input.  As
long as you use the routines \verb+header()+, \verb+start_html()+,
\verb+start_form()+, \verb+end_form()+, and \verb+end_html()+ with HTML
emitting functions placed between \verb+start_html()+ and
\verb+end_html()+ and HTML form widgets only placed between
\verb+start_form()+ and \verb+end_form()+, the HTML produced should be
valid (if not aesthetically pleasing when printed).  However, this is
a good way to check for run-time warnings and other problems.
Continuing the above example, a \ctrld\ would give us
\begin{verbatim}
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML><HEAD><TITLE>Add Me</TITLE>
</HEAD><BODY><H1>Add Me</H1><HR><FORM METHOD="POST"  ENCTYPE="application/x-www-form-urlencoded">
<P>First Number: <INPUT TYPE="text" NAME="field1" VALUE=""></P>
<P>Second Number: <INPUT TYPE="text" NAME="field2" VALUE=""></P>
<P><INPUT TYPE="submit" NAME="add" VALUE="add"> <INPUT TYPE="reset" VALUE="clear"></P>
</FORM><HR></BODY></HTML>
\end{verbatim}

To make your script execute as if it received user input, enter the
\verb+-NAME+ that you gave each widget followed by an equals sign and
a test value you would like it to have.  If the value has spaces in
it, like {\em hello there}, it should be enclosed in quotes.  When you
are done with the list, type \ctrld.  For \underline{add.cgi}, we
could enter
\begin{verbatim}
field1=3<newline>
field2=4<newline>
<control>D
\end{verbatim}
The script would emit:
\begin{verbatim}
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML><HEAD><TITLE>Add Me</TITLE>
</HEAD><BODY><H1>Add Me</H1><P>3 + 4 = <strong>7</strong>
</P></BODY></HTML>
\end{verbatim}
Again, it could also generate Perl warnings or programmer-defined
error messages.

What if you have a widget that allows the user to select several
values to return to the CGI script (for example, a
\verb+checkbox_group+)?  Then you simply repeat the
widget-name-equals-value combination  for each value:
\begin{verbatim}
operating_systems=AIX<newline>
operating_systems='Sun OS'<newline>
<control>D
\end{verbatim}

\section{Enabling Online CGI Execution}

To run a CGI script on the server, you will need to take the following
steps:

\begin{enumerate}

  \item starting at your home directory, create a directory called
{\bf public\_html};  

  \item \verb+cd+ to {\bf public\_html} and create a directory called
{\bf cgi-bin};

  \item \verb+cd+ to {\bf cgi-bin} and type 
\begin{verbatim}
  fs sa . system:anyuser rlwk
\end{verbatim}
The \verb+rl+ (read and lookup) privileges
  are needed to run any CGI script.  The \verb+wk+ (write and lock)
  privileges will be needed because you will be locking and writing to
  a file from a CGI script for Project 2. {\bf You should set the
  privileges back to \verb+rl+ when you are done testing the project.} 

  \item make sure the Perl script is contained in a file that ends
with the extension \verb+.cgi+;

  \item make the CGI script executable (for example, 
\verb!chmod a+x script.cgi!). 

\end{enumerate}

Once this is complete, the script may be run as described in the
following section.

\section{Online Execution}

Bring up your favorite browser, say \verb+netscape+.  Open the URL
\begin{verbatim}
http://cgi.cs.rpi.edu/rcs/<your-rcs-id>/<your-script-prefix>.cgi
\end{verbatim}
For example, if I wanted to run a script called \underline{add.cgi}, I
would open 
\begin{verbatim}
http://cgi.cs.rpi.edu/rcs/ziantl/add.cgi
\end{verbatim}
Your script should now execute, most likely generating a form for the
user to enter input.  Once the user submits the form, your script will
produce another HTML page in response which will be displayed
automatically.


\section{Server Errors}

Suppose you are running in {\em online mode} and receive the following
message or something like it:
\begin{verbatim}
Internal Server Error

The server encountered an internal error or misconfiguration and was
unable to complete your request. 

Please contact the server administrator, www@cs.rpi.edu and inform
them of the time the error occurred, and anything you might have 
done that may have caused the error. 
\end{verbatim}

In this case, you should go back to {\em offline mode} and test your
script again thoroughly.  You will probably find that you have an
error.  If everything seems to run fine offline, but you still get a
server error message online, please contact me.  Please do not contact
\verb+www@cs.rpi.edu+.  Take note that this is not an RCS server, so
sending mail to anyone at ACS will not be productive.

\end{document}

\underline{Running a CGI Script} \\

\end{center}

%%\section{CGI.pm}

%%The CGI Perl Module is available in the directory
%%\verb+/dept/cs/complang/perl/module+.  You should make a soft link to
%%it from any directory in which you are going to execute your CGI
%%script (that is, \verb+ln -s /dept/cs/complang/perl/module/CGI.pm+).  If
%%you receive the following message from Perl:
%%\begin{verbatim}
%%Can't locate CGI.pm in @INC at ./vote.cgi line 7.
%%BEGIN failed--compilation aborted at ./vote.cgi line 7.
%%\end{verbatim}
%%then you don't have access to it from the directory you are in and
%%need to make the link.  For the purposes of this project, the only
%%directory you will need to make a link from is
%%\verb+~/public_html/cgi-bin+ (see {\em Enabling Online CGI Execution}
%%below) unless you want to do offline testing in another directory.

\section{Offline Execution}

Most of the development of your CGI script should be done in this mode
of execution.  To get offline execution, you simply run the CGI script
as a normal Perl script on, for example, an IBM workstation.  Suppose
you execute the script \underline{add.cgi}.  You will get the
following prompt:
\begin{verbatim}
(offline mode: enter name=value pairs on standard input)
\end{verbatim}

If you hit \ctrld\ at this point, the script should produce the HTML
corresponding to the form that the user will use to enter input.  As
long as you use the routines \verb+header()+, \verb+start_html()+,
\verb+start_form()+, \verb+end_form()+, and \verb+end_html()+ with HTML
emitting functions placed between \verb+start_html()+ and
\verb+end_html()+ and HTML form widgets only placed between
\verb+start_form()+ and \verb+end_form()+, the HTML produced should be
valid (if not aesthetically pleasing when printed).  However, this is
a good way to check for run-time warnings and other problems.
Continuing the above example, a \ctrld\ would give us
\begin{verbatim}
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML><HEAD><TITLE>Add Me</TITLE>
</HEAD><BODY><H1>Add Me</H1><HR><FORM METHOD="POST"  ENCTYPE="application/x-www-form-urlencoded">
<P>First Number: <INPUT TYPE="text" NAME="field1" VALUE=""></P>
<P>Second Number: <INPUT TYPE="text" NAME="field2" VALUE=""></P>
<P><INPUT TYPE="submit" NAME="add" VALUE="add"> <INPUT TYPE="reset" VALUE="clear"></P>
</FORM><HR></BODY></HTML>
\end{verbatim}

To make your script execute as if it received user input, enter the
\verb+-NAME+ that you gave each widget followed by an equals sign and
a test value you would like it to have.  Note that giving a widget a
name containing spaces will work in online mode but will be a problem
in offline mode.  If the value has spaces in it, like {\em hello
there}, it should be enclosed in quotes.  When you are done with the
list, type \ctrld.  For \underline{add.cgi}, we could enter \\

\noindent
\verb+field1=3+ \ret \\
\verb+field2=4+ \ret \\
\ctrld \\

The script would emit:
\begin{verbatim}
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML><HEAD><TITLE>Add Me</TITLE>
</HEAD><BODY><H1>Add Me</H1><P>3 + 4 = <B>7</B>
</P></BODY></HTML>
\end{verbatim}
Again, it could also generate Perl warnings or programmer-defined
error messages.

What if you have a widget that allows the user to select several
values to return to the CGI script (for example, a
\verb+checkbox_group+)?  Then you simply repeat the
widget-name-equals-value combination  for each value: \\

\noindent
\verb+operating_systems=AIX+ \ret \\
\verb+operating_systems='Sun OS'+ \ret \\
\ctrld \\

Instead of typing in the data each time, you can create several files
of the proper format and then run the script by redirecting standard
input to come from a file.  For example, if we have a file called
\underline{input.batch}, with the following contents:

%%email=ziantzl@cs.rpi.edu
\begin{verbatim}
N03=yes
G11=yes
QN03=1
QG11=3
name="Louis Ziantz"
address="CS Dept, RPI"
city=Troy
state=NY
zip=12180
comm_stat=Noncommercial
username=ziantzl
password=youkilledkenny
password2=youkilledkenny
\end{verbatim}

\noindent
we can run \underline{cart.cgi} as \verb+cart.cgi < input.batch+.

\section{Enabling Online CGI Execution}

To run a CGI script on the server, you will need to take the following
steps:

\begin{enumerate}

  \item starting at your home directory, create a directory called
{\bf public\_html};  

  \item \verb+cd+ to {\bf public\_html} and create a directory called
{\bf cgi-bin};

  \item \verb+cd+ to {\bf cgi-bin} and type 
\begin{verbatim}
  fs sa . system:anyuser rlikw
\end{verbatim}
The \verb+rl+ (read and lookup) privileges are needed to run any CGI
  script.  The \verb+ikw+ (write and lock) privileges will be needed
  because you will be creating, locking, and writing to a file from a
  CGI script for Project 2. You should only copy your script to
  cgi-bin when you want to do online testing.  {\bf When testing is
  done, you should remove it from cgi-bin and set the directory's
  privileges back to \verb+rl+ or less.}

  \item make sure the Perl script is contained in a file that ends
with the extension \verb+.cgi+;

  \item make the CGI script executable (for example, 
\verb!chmod a+x script.cgi!).  Note the \verb|a+x|.  It must be
executable by everyone, not just you.

\end{enumerate}

Once this is complete, the script may be run as described in the
following section.

\section{Online Execution}

Bring up \verb+netscape+.  Open the URL
\begin{verbatim}
http://cgi.cs.rpi.edu/rcs/{your-rcs-id}/{your-script-prefix}.cgi
\end{verbatim}

For example, if I wanted to run a script called \underline{add.cgi}, I
would open 
\begin{verbatim}
http://cgi.cs.rpi.edu/rcs/ziantl/add.cgi
\end{verbatim}
Your script should now execute, most likely generating a form for the
user to enter input.  Once the user submits the form, your script will
produce another HTML page in response which will be displayed
automatically.  If you develop your script on a different CGI server,
make sure that it works correctly using the above URL.


\section{Script Errors}

If you are using the module CGI::Carp.pm and running in {\em online
mode}, fatal errors generated by Perl will be displayed by your
browser, for example: 
\begin{verbatim}
Software error:

Undefined subroutine &main::foo called at /usr/local/www/rcs/ziantl/Test/cart.cgi line 14. 

Please send mail to this site's webmaster for help. 
\end{verbatim}

\noindent
At this point, you should go back to {\em offline mode} to fix
the problem before running in {\em online mode} again.  Note that
Perl warning messages will not be displayed in {\em online mode}. 

Suppose you are running in {\em online mode} and receive the following
message or something like it:
\begin{verbatim}
Internal Server Error

The server encountered an internal error or misconfiguration and was
unable to complete your request. 

Please contact the server administrator, www@cs.rpi.edu and inform
them of the time the error occurred, and anything you might have 
done that may have caused the error. 
\end{verbatim}

\noindent
In this case, you 1) are probably not using the module CGI::Carp.pm
and 2) should go back to {\em offline mode} and test your
script again thoroughly.  You will probably find that you have an
error.  If everything seems to run fine offline, but you still get a
server error message online, please contact me.  

In either instance, {\bf please do not contact
\verb+www@cs.rpi.edu+.  Take note that this is not an RCS server, so
sending mail to anyone at ACS will not be productive.}

\end{document}


Carp Error message :

Software error:

Undefined subroutine &main::foo called at /usr/local/www/rcs/ziantl/Test/cart.cgi line 14. 

Please send mail to this site's webmaster for help. 
    







    




\end{document}



    



