Questions and answers

Since the same script puts up a form that asks questions and also retrieves the answers to those questions, we need to be able to tell in which phase of the operation we are. We do that by testing $data to find out whether it is full or empty. If it is full, we find that all the data typed into the fields of the form by the user are there, with the fields separated by &. For instance, if the user had typed “Anne” into the first-name box and “Smith” into the surname box, this string would arrive:

xname=Anne&sname=Smith

or, if the browser is being very correct:

xname=Anne;sname=Smith

We have to dissect it to answer the customer’s question, but this can be a bit puzzling. Not only is everything crumpled together, various characters are encoded. For instance, if the user had typed “&” as part of his response, e.g., “Smith&Jones”, it would appear as “Smith%26Jones”. You will have noticed that “26” is the ASCII code in hexadecimal for “&”. This is called URL encoding and is documented in the HTTP RFC. “Space” comes across as “+” or possibly “%20”. For the moment we ignore this problem. Later on, when you are writing real applications, you would probably use the “unescape” function from CGI.pm to translate these characters.

The strategy for dealing with this stuff is to:

  1. Split on either “&” or “;” to get the fields

  2. Split on “=” to separate the field name and content

  3. (Ultimately, when you get around to using it) use CGI::unescape($content), the content to get rid of URL encoding

See the first few lines of the following subroutine get_name(). This is the script .../cgi-bin/script2_html, which asks questions and gets the answers. There are commented out debugging lines scattered through the script, such as:

#print "in get_name: ARGS: @args, DATA: $data<BR>";

Put these in to see what is happening, then turn them off when things work. You may like to leave them in to help with debugging problems later on.

Another point of style: many published Perl programs use $dbh for the database handle; we use $dbm:

#! /usr/local/bin/perl -wT
use strict;
use DBI();
use CGI;
use CGI::Carp qw(fatalsToBrowser);

my ($data,@args);

$data=<>;

if($data)
    {
    &get_name($data);
    }
elsif($ENV{'PATH_INFO'} eq "/whole_database")
    {
    $data="xname=%&sname=%";
    &get_name();
    }
else
    {
    &ask_question;
    }
print "</BODY></HTML>";


sub ask_question
{
&print_header("ask_question");

print qq(<A HREF="/cgi-bin/script2_html/whole_database">
Click here to see the whole database</A>

<BR><FORM METHOD='POST' ACTION='/cgi-bin/script2_html/name'>
Enter a first name <INPUT TYPE='TEXT' NAME='xname' SIZE=20><BR>
and or a second name <INPUT TYPE='TEXT' NAME='sname' SIZE=20><BR>
<INPUT TYPE=SUBMIT VALUE='ENTER'>);

}

sub print_header
{
print qq(content-type: text/html\n\n
<HTML><HEAD><TITLE>$_[0]</TITLE></HEAD><BODY>);
}

sub get_name
{
my ($t,@val,$ref,
    $mesg,$dbm,$query,$xname,$sname,$sth,$rows);

&print_header("get_name");
#print "in get_name: ARGS: @args, DATA: $data<BR>";
    $xname="%";
    $sname="%";
@args=split(/&/,$data);

foreach $t (@args)
    {
    @val=split(/=/,$t);
    if($val[0] eq "xname")
        {
        $xname=$val[1] if($val[1]);
        }
    elsif($val[0] eq "sname")
        {
        $sname=$val[1] if($val[1]);
        }
    }

# open a database
$dbm=DBI->connect("DBI:mysql:database=people;host=localhost",'webserv')
    or die "didn't connect to people";

# get it back
$query=qq(select xname, sname from people where xname like ? 
and sname like ?);
$sth=$dbm->prepare($query) or die "failed to prepare $query: $!";
#print "$xname, $sname: $query<BR>";

# $! is the Perl variable for the current system error message

$sth->execute($xname,$sname) or die "failed to execute $dbm->errstr()<BR>";
$rows=$sth->rows;
#print "$rows: $rows $query<BR>";

if($sname eq "%" && $xname eq "%")
    {
    print qq(<table border=1 width=70%><caption><h3>The Whole Database (3)</h3></
caption>);
    }
else
    {
    print qq(<table border=1 width=70%><caption><h3>The $rows People called $xname 
$sname</h3></caption>);
    }
    
print qq(<tr><align left><th>First name</th><th>Last name</th></tr>);
while ($ref=$sth->fetchrow_hashref)
    {
    print qq(<tr align right><td>$ref->{'xname'}</td><td> $ref->{'sname'}</td></tr>);
    }
print "</table></BODY></HTML>";
$sth->finish;
# close the database connection
$dbm->disconnect;
}

The Config file is ...site.cgi/httpd3.conf.

User webuser
Group webgroup
ServerName www.butterthlies.com
DocumentRoot /usr/www/APACHE3/APACHE3/site.cgi/htdocs

# for scripts in .../cgi-bin
/cgi-bin /usr/www/APACHE3/APACHE3/cgi-bin
DirectoryIndex /cgi-bin/script2_html

Kill Apache and start it again with ./go 3.

The previous script handles getting data to and from the user and to and from the database. It encapsulates the essentials of an active web site — whatever language it is written in. The main missing element is email — see the following section.