Megan's Notebooks
MEGAN'S NOTEBOOKS // HTML Tags // SOURCES // CGI & FORMS // LINKS// HELP

Step by Step Simple Form & CGI

Here is the source for sample_form.html and for sample.cgi .The form and the cgi script that this tutorial uses. Download them, tweak them to run in your directories and don't forget to change the extensions back to .html and .cgi when you are ready to use them.

Let's write a form first.

1.) Start with a normal HTML document:

<html><head><title>Generic_Page</title></head>

<body></body></html>


2.) Tell the Client we are beginning a form by inserting the <FORM ...> element. This element has two attributes that we are concerned with:

METHOD
This describes how we are going to get the information the user types into our form to the server. The POST Method is preferred.

ACTION
This is the URL that is set up to receive our form when it is ready for submission. It is possible with some browsers to use a mailto: url as the submission url. We will talk about that later.

A completely filled out form line might look like this:

<FORM METHOD="POST" ACTION="http://www.worldwideink.com/cgi-bin/sample.cgi">


3.) Now we need to add a field for the user to fill in. To do this use the <INPUT ...> element. Again there are only a few attributes we need to worry about right now:

NAME
This is the name of the variable that will hold the value the user types in. You can think of this as a label for whatever the user types.

SIZE
This is a number that tells how long the blank should be in characters. This is an optional attribute. Remember, bigger is not always better.

TYPE
We will be using the default value of this attribute that defines what type of an input field it is. Because of our use of the default value, it doesn't even need to appear in our HTML.

There are several types of input fields, all very well described in various HTML tutorials and in another notebook . Look there for how to do CHECKBOXES, RADIO BUTTONS etc.

An input element might look like this:

<INPUT NAME="pname" SIZE=36>


But, I wanna do those multi-line inputs!

4.) Okay, to do those you have to use a different element, the <TEXTAREA ...> </TEXTAREA> element. This is just like doing anchors in a normal html form. Instead of describing and naming a url, though, we will describe a field, and if wanted specify a default value. The following are some more attributes we will be concerned with:

rows
This is how many rows you want in the field. Rows are analogous to the lines on a page.

cols
This is how many columns you want the field to be. Columns are analogous to the width of the field.

<TEXTAREA NAME="firstname" rows=10 cols=10></TEXTAREA>

You can put some default text where you would put the hyperlink if this were an anchor.

<TEXTAREA NAME="firstname" rows="10" cols="10">This text will be in the field when you start editing it. Since this text is on different lines separated by returns, it would start off on different lines in the form too. </TEXTAREA>


5.) We are almost done, we just need to add a way for the user to submit the form. A clear button would be nice too. We use a modified INPUT element to create buttons for these purposes. It is pretty much the same old INPUT, but with a different set of attributes:

TYPE
This says what kind of a field this is. We will be using the submit type to submit the form, and the reset type to clear the form and reset all fields to their default values.

VALUE
This is the label text for this button.

For example to allow the user to submit and clear we could use these:

<input type="submit" value="Send In This Form">
<input type="reset" value="Clear">

Note: The clear button doesn't actually clear the form, it merely resets all the fields to their default values. If the field started out as empty it will be returned to the empty state. However fields starting out with text in them, will have that text restored to them if it has been modified.


6.) Ok, let's wrap this up. You end a form with the </FORM> element. Provide instructions on what to fill the blanks in with.

So. The whole html document with our form looks like:

<HTML> <HEAD> <TITLE>A Very Simple Form</TITLE> </HEAD><BODY>

<FORM METHOD="POST"ACTION="http://www.worldwideink.com/cgi-bin/sample.cgi">

What's your name? <TEXTAREA NAME="firstname" rows=10 cols=10></TEXTAREA>

<INPUT TYPE="SUBMIT" VALUE="Send In This Form">

<INPUT TYPE="RESET"VALUE="Clear">

</FORM>

</BODY> </HTML>

To see it in action go to sample_form.html


Now we'll write the cgi script that the form calls!

1.) On the first line, you need to tell your shell how to run perl on your system. This is typically done with a line that tells the shell where perl is and to execute it. An example is:
#!/usr/local/bin/perl

You can typically find perl on your system by typing which perl.


2). Comments are nice, and help people understand what is going to happen. In perl a comment starts with a # symbol. The comments should include:
  • The name of the program (you will appreciate this if you ever print it)
  • Who wrote the code, when, and why
  • Any libraries you are going to use (i.e. cgi-lib.pl)

3.) Since we are creating HTML on the fly, make sure we send a response header so that the server knows that it's sending HTML. In Perl we use:

print "Content-type: text/html\n\n";

\n is the Perl newline character. The response header must have a blank line after it, hence the second \n.

All perl statements must end in a semicolon.


4.) Okay, this next part looks scary but don't worry if you don't understand it all, you don't have to. It just works! The following Perl code essentially reads and parses the user input of the form.

if ($ENV{'REQUEST_METHOD'} eq "get") { $buffer = $ENV{'QUERY_STRING'}; }
else { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
@nvpairs = split(/&/, $buffer);
foreach $pair (@nvpairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}

The above can also be accomplished by just referring to a sub-routine of a perl library called cgi-lib.pl by Steve Bremmer. To use it instead, place these lines near the beginning of your script:

push(@INC," /usr/local/httpd/apache/cgi-bin");
require("cgi-lib.pl");

And then call the sub-routine ReadParse like this:
&ReadParse(*input);

But for now we'll stick to the messy way.


5.) Ok, let's print out the HTML code. Remember, we have to quote strings, and HTML does not make a line break, unless it sees a paragraph or linebreak marker. Also, characters that Perl might interpret as Perl need to be escaped. To make our output more human-readable, we probably want to break it up with new lines between significant elements. To print a new line in perl, print the string "\n". My code looks like this:

print "<HTML>\n";
print "<HEAD>\n";
print "<TITLE>HTML Written by sample.cgi</TITLE>\n";
print "</HEAD>\n";
print "<BODY BGCOLOR=\"\#FFFF80\" TEXT=\"\#000000\">\n";
print "<BASEFONT SIZE=4>\n";
print "<CENTER>\n";
print "<P>Hello, $FORM{'firstname'}!\n";
print "</CENTER>\n";
print "</BODY>\n";
print "</HTML>\n";

Note that we've escaped the # with a back slash \ in the BGCOLOR attribute so that Perl doesn't think we are writing a comment. Some other characters in strings that will need escaping are :

@ like in e-mail addresses
/ like in URL's
" like in tag attributes


Note:Instead of using the print command over and over, here's a neat trick. At the beginning of the HTML to be printed use this:

print <<__END_OF_HTML__;

Put all your HTML here, then:

print __END_OF_HTML__;


print << is essentially saying, "print everything up to __END_OF_HTML__." You will also avoid having to escape all the special characters and won't need the newline operators!
The whole sample.cgi script with added comments looks like :

#!/usr/local/bin/perl

## First, since we are creating HTML on the fly, make sure
## we send a response header so that the server knows that
## it's sending HTML.

print "Content-type: text/html\n\n";

## Read and 'decode' the data received by the server so that
## we can use it in our HTML.
if ($ENV{'REQUEST_METHOD'} eq "get") { $buffer = $ENV{'QUERY_STRING'}; }
else { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
@nvpairs = split(/&/, $buffer);
foreach $pair (@nvpairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}

##Create the HTML with the 'decoded' data plugged in.

print "<HTML>\n";
print "<HEAD>\n";
print "<TITLE>HTML Written by sample.cgi</TITLE>\n";
print "</HEAD>\n";
print "<BODY BGCOLOR=\"\#FFFF80\" TEXT=\"\#000000\">\n";
print "<BASEFONT SIZE=4>\n";
print "<CENTER>\n";
print "<P>Hello, $FORM{'firstname'}!\n";
print "</CENTER>\n";
print "</BODY>\n";
print "</HTML>\n";

That's it ! Remember to use ascii or text mode (not binary) when you upload it to the server and of course you'll need to set the mode of the script to execute with:
chmod 755 sample.cgi

If you still can't get your forms to fly read about the most common errors people make when they first start sriting cgi.

megan@worldwideink.com

visitors since 1/1/96