\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, Summer 98} \\
\underline{Project 2} \\
{\bf Due : Friday, June 12 at midnight} \\
{\bf Weight : } 20\% of course grade \\
Instructor : Moorthy

\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}.  Before handing it in, make sure it works
using \verb+netscape+ running on an IBM workstation.  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}  
You have been hired by a small software company.  They would like to
make some of the CGI scripts they have developed available from their
web page.  Your first project is to develop a simple Perl script that
meets the specifications detailed in this document.  Your initial
script will eventually be refined into a full-fledged shopping cart
application. 

\section{Specification}

They would like a single script that both generates an ordering form and
processes a user's order.

\subsection{Form Generation}

Products are stored in a file called
\underline{catalog.dat}.  A line of the file has the following format:
\begin{verbatim}
{product-code}:{product-name}:{commerical-price}:{noncommercial-price}:{product-description}
\end{verbatim}
For example, 
\begin{verbatim}
C05:Net Chat:50:20:New version; can handle any number of visitors!
\end{verbatim}
Product codes consist of three characters and are unique.
You will first need to read and store this data in some
reasonable data structures (perhaps separate hashes for product names,
commercial prices, noncommercial prices, and descriptions, each using
product code as keys, or separate arrays for each data field).

The \verb+<TITLE>+ of the order page should be \verb+Order Form for New Customers+.  
The page itself should consist of the following:

\begin{itemize}

  \item A \verb+<H1>+ heading that reads \verb+Order Form for New Customers+.

  \item A horizontal rule (\verb+<HR>+).

  \item Text that indicates how the user should select scripts, that
  the form must be completely filled out to process an order, and that
  a username and password must also be provided.
 
  \item A horizontal rule (\verb+<HR>+).

  \item A \verb+<H2>+ heading that reads \\
\verb+Please select the scripts you wish to purchase and the number of licenses:+.  This is
  followed by a series of product listings, each separated by a
  \verb+<P>+.  The listings do not have to be displayed in any
  particular order. 

  \begin{itemize}

     \item Each listing should start with a checkbox.  Use the product code
  as the \verb+-NAME+ of the checkbox.  The box should not be checked
  at the beginning.

     \item The label \verb+Item:+ should appear in bold on the same
     line as the checkbox.  The label should be followed by the product name.

     \item The label \verb+Commercial price:+ should appear next in
     bold on the same line.  It should be followed by the commercial
     price of the product (the price should include a dollar sign).

     \item The label \verb+Noncommercial price:+ should appear next in
     bold on the same line, followed by the noncommercial
     price of the product (the price should include a dollar sign).

     \item The label \verb+Quantity:+ should appear in bold on the same
     line as the checkbox, followed by a textfield of
     width 3 with an default value of 1.  I would suggest that each
     textfield be given a name that can be constructed from the
     corresponding product code.  Since product codes are of fixed
     length, you can simply prepend a \verb+'Q'+ to the product code,
     for example.

     \item On the next line (emit a \verb+<BR>+), the product
     description should appear in italics.

  \end{itemize}

  \item A horizontal rule (\verb+<HR>+).

  \item A \verb+<H2>+ heading that reads \verb+Contact Information:+.

  \item An appropriate label and a textfield that allows the user to
  enter a name (set the width of the field to 40).

%  \item An appropriate label and a textfield that allows the user to
%  enter an email address (set the width of the field to 40).

  \item An appropriate label and a textfield that allows the user to
  enter a street address (set the width of the field to 40).

  \item An appropriate label and a textfield that allows the user to
  enter a city (set the width of the field to 25).  On the same line,
  a label and a popup menu with postal abbreviations for all 50 states
  followed by another label and a textfield that allows the user to
  enter a zip code (set the width of the field to 9 and make this the
  maximum number of characters that can be entered).

  \item A bold label \verb+Intended use for script:+ followed by a radio
  group list consisting of two options --- Commercial and
  Noncommercial.  Both options should be on the same line.  Neither
  box should be checked at the beginning.

  \item A horizontal rule (\verb+<HR>+).

  \item Text indicating that the user should now choose a username and
  password that will be used to access the scripts once payment is
  received.  Point out that they should enter the password twice.

  \item An appropriate label and a textfield that allows the user to enter a username.

  \item An appropriate label and a password field that allows the user to enter a password.

  \item An appropriate label and a password field that allows the user
  to re-enter the password.

  \item A horizontal rule (\verb+<HR>+).

  \item A submit button titled \verb+Submit Order+ and a reset button titled
  \verb+Reset Order+.

\end{itemize}

\subsection{Form Processing}


\subsubsection{Validating User Input {\em(Bonus --- 15 points)}} 

%% email address,
Before any processing occurs, your code should verify that the contact
information portion of the form was completely filled out.  If the
name,  address, city, zip code, username or password
fields have no data or if none of the ``intended use'' boxes were clicked
by the user, an error page should be generated.  The error page should
indicate which field was not completed by the user (if more than one
is blank, you simply need to issue a message about the first blank
field encountered in your tests).  In addition, if the original
password entered doesn't match the password re-entered by the user, a
different error page should be displayed indicating that the two
passwords were not the same.

After verifying this data, the product file must be read as in the form
generation stage.

The script should then determine whether anything was ordered by the
user.  If none of the boxes were checked or quantities less than 1
were provided for those boxes that were checked, an error page
should be generated indicating that no items were ordered.

Notes on error pages:

\begin{itemize}

  \item any error page generated should inform the user that he
or she may use the Back option on a browser to go back to the form and
rectify any mistakes.

  \item if an error page is generated, no data should be written to
\underline{orders.dat} (see Section~\ref{sec:process}).

\end{itemize}

\subsubsection{Processing an Order}
\label{sec:process}

%% {email-address}
(Note that even if you are not doing the bonus part, you will need to
read the product file as in the form generation stage.)  A valid order
should be appended to a file called \underline{orders.dat}.  An order
consists of several lines written out to the file with the following
format:
\begin{verbatim}
{name}
{street-address}
{city}:{state}:{zip-code}
{intended-use}
{username}
{encrypted-password}
{order-line-1}
...
{order-line-n}
%%
\end{verbatim}

Notice that city, state, and zip code are separated by colons.
Intended use is either Commercial or Noncommercial.  You can encrypt
the password by calling the Perl builtin function \verb+crypt+.  Use
the text to be encrypted as the first argument, and pass the string
\verb+"bx"+ as the second.  A person's order ends with two percent
signs.  An order line is of the following form:
\begin{verbatim}
{product-code}:{quantity}
\end{verbatim}

The script should then generate a page containing a purchase summary
for the user.  The \verb+<TITLE>+ of the page should be
\verb+Order Summary for {name}+ where \verb+{name}+ is the name input
by the user.  It should have the following format:
\begin{itemize}

    \item A \verb+<H1>+ heading \verb+Order Summary for {name}+ where
\verb+{name}+ is the name input by the user.

    \item A horizontal rule (\verb+<HR>+).

    \item A \verb+<H2>+ heading that reads \verb+Contact Information:+.

%%    \item An appropriate label in bold and the user's email address.

    \item An appropriate label in bold and the user's street address.

    \item The user's city, state, and zip code with appropriate bold
    labels on the same line.

    \item A horizontal rule (\verb+<HR>+).

    \item A \verb+<H2>+ heading that reads \verb+Other Information:+.

    \item An appropriate label in bold and the user's intended use for
the software.

    \item An appropriate label in bold and the user's username.

    \item The text \verb+Password successfully logged.+ in bold.

    \item A horizontal rule (\verb+<HR>+).

    \item A \verb+<H2>+ heading that reads \verb+Purchase Information:+.

    \item One or more lines indicating the items ordered.  Each line
    should consist of the product name, the quantity, and the item's
    price (commercial or noncommercial) with appropriate bold labels.
    
    \item An appropriate label and the total number of items ordered.

    \item An appropriate label and the total due.  Note that total due
    is computed based on the number of items ordered and the
    price of each item (either commercial or noncommercial
    based on the intended use of the software).

\end{itemize}
 
\section{Details}

\begin{itemize}

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

  \item Use the module CGI.pm (\verb+use CGI qw(:standard);+).

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

  \item Use the module CGI::Carp.pm (\verb+use CGI::Carp qw(fatalsToBrowser);+)

  \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 Assume any username entered by the user does not already exist.

  \item You will need to lock \underline{catalog.dat} for
  concurrent read (no write) when you read it for input.

  \item You will need to lock \underline{orders.dat} for
  exclusive write (no read) when you write to it.

  \item If you do the bonus part, append the string \verb+"-- Bonus"+
  in the \verb+<TITLE>+ and \verb+<H1>+ heading of the generated form.

  \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 several subroutines.  Other activities, such as reading
  the catalog file and generating the different HTML error pages are
  all candidates for separate subroutines.

  \item Keep the use of global variables to a minimum.  Global
  ``constants'' such as filenames are fine.  It is acceptable to
  make the product 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.  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=krishm@cs.rpi.edu
\begin{verbatim}
N03=yes
G11=yes
QN03=1
QG11=3
name="Krishna Moorthy"
address="CS Dept, RPI"
city=Troy
state=NY
zip=12180
comm_stat=Noncommercial
username=krishm
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/krishm/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/krishm/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/krishm/Test/cart.cgi line 14. 

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




\end{document}



    



