O'Reilly logo

CGI Programming on the World Wide Web by Shishir Gundavaram

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

C. CGI Modules for Perl 5

If you are tired of writing code to create forms, decoding form information, or maintaining state between multiple forms, you can make your life easier by using the freely available CGI modules for Perl 5. However, unless you are familiar with programming, it will be difficult to fully grasp how these modules work internally.

C.1 Overview of Modules

First, here is a list of the available modules. We will look at an example that incorporates the functionality from some of these modules shortly.

Base.pm

This is the core module that contains common methods (i.e., functions) that some of the other classes depend on. These include methods to read form information (the module does not parse or decode the data), log debug messages, implement socket I/O for maintaining state, and access and manipulate data from environment variables, such as the client's acceptable MIME content types.

If you are familiar with object-oriented programming, Base.pm represents the base class, from which other classes “inherit” methods and data structures. The “child” classes can override the methods from the base class to create modified functions, or implement new ones.

BasePlus.pm

This module consists of functions to handle the new multipart forms generated by “file upload”--a feature new to Netscape 2.0. The file upload feature allows users to send files on their local machines as part of a form. This is a very powerful feature, but decoding the data can be a hassle. So, you should use either this module or the CGI_Lite module to handle multipart forms.

Request.pm

You can parse and decode form and query data with this module. That's all there is to it!

Form.pm

Have you ever wished you could create forms much more quickly and easily than outputting a series of HTML tags? If so, the Form module is the one for you! You no longer have to remember how to create a radio button or a scrolled down list.

In addition, this module allows you to easily decode and parse form and query data. The functions responsible for this are inherited from the Base.pm and Request.pm modules.

MiniSvr.pm

With this module, you can implement a “mini HTTP daemon” which can be forked from a CGI application to maintain state between multiple form invocations. The daemon sits on a port with a relatively short timeout, waiting for a request. It then serves the request and terminates. Now, imagine what will happen to your host machine if the rate of process creation (i.e., forking) exceeds that of termination.

You need to be careful when using this module to maintain state, as it creates multiple processes to handle requests. If the rate of process creation exceeds that of termination, your server will become overloaded and may result in serious problems.

However, this module can be very helpful if used correctly, as all socket I/O is handled by the module so that you don't have to worry about such things as choosing the correct port number, establishing the socket, or reading from the socket.

Response.pm

Though not a part of the official CGI module distribution at the time of this writing, this module contains functions that make it easier to output HTML headers. For example, if you don't want a document to be cached, you can call a method that will automatically output the Pragma and Expires headers for you.

Carp.pm

This module is independent, in that it does not inherit any functionality from the base class. However, it is a very useful module that allows you to format error messages sent to the server log file or redirect them to the browser or another file.

C.2 Form Creation and Parsing

Here is a simple example that creates a form and parses the data using the modules that we've just discussed. The dynamic form that is output by the program is shown in Figure C-1.

Figure C.1: Form created from Perl 5 modules

images

Now, let's look at the program:

#!/usr/local/bin/perl5
use CGI::Form;
use CGI::Response qw(:Simple);
use CGI::Carp;

Before we can use any of the methods in the CGI modules, we have to import them into our program. In the case of CGI::Response, some of the “simple” methods, such as those that output the Content-type and Pragma HTTP headers, are not exported by the module so we have to literally specify it.

print NoCache ();

The NoCache method from the CGI::Response class outputs the following header information:

Pragma: no-cache
Content-Type: text/html
Expires: Mon, 29 Jan 1996 00:53:49 GMT

which instructs the server that HTML data is about to follow, and that it should not cache the document.

$cgi_form = new CGI::Form ();
$user = $cgi_form->param ('name');

We create a new instance of the Form object and store it in $cgi_form. Then, we retrieve the value for the form field labeled name so that we can use it to personalize the title of the document for successive forms.

Here we see an example of inheritance. The param method is implemented in the CGI::Request module, which is inherited by CGI::Form. As a result, we can access the method as though it was part of CGI::Form.

if ($user) {
    $remote_user = "Welcomes $user";
} else {
    $remote_user = join (" ", "- Welcome from", $cgi_form->cgi->var ("REMOTE_HOST"));
}

Here, we set the $remote_user variable to a welcome message. If the $user variable is not defined, we use the remote host name instead. Here is another interesting call. The cgi method is implemented in the CGI::Request module and interfaces with CGI::Base. The var method is defined in CGI::Base and returns the value of a specific environment variable.

print <<Start_HTML;
<HTML>
<HEAD><TITLE>Welcome to Shishir's Track & Field Emporium</TITLE></HEAD>
<BODY>
<H1>Track and Field $remote_user</H1>
<HR>
Start_HTML
&display_form ($cgi_form);
print <<End_HTML;
<HR>
</BODY>
</HTML>
End_HTML
exit (0);

We output the header and footer with a form in between. The form is created by the display_form subroutine, which expects an instance of the CGI::Form class.

The display_form subroutine creates a form by calling several methods in the CGI::Form class. Not only do these methods output the necessary HTML to create the form, but they also check to see if there is any form data that is being passed to the program, and use that data as default information for the various fields--providing that the field (names) are the same. This is actually an example that saves state, and works as a result of setting the ACTION attribute on the form to point back to this script; there is always data passed to the program if the user submits the form.

sub display_form
{
    local ($form) = @_;

Here the $form refers to an instance of the CGI::Form object that we created earlier.

print $form->startform ();
    print “Name: “;
    print $form->textfield ('name'), “<BR>", “\n";
    print “E-Mail Address: “;
    print $form->textfield ('email'), “<BR>", “\n";

The startform method outputs the necessary <FORM> tag to start the form. The startform method uses a default ACTION of the current script, and a default METHOD of POST.

The textfield method creates a text field. If the form data passed to this program has a field titled name, the method will use the passed-in value as a default. In other words, this is what it does (assume that form data is stored in the %FORM associative array):

$value = $FORM{'email'};
print qq|<INPUT TYPE="text" NAME="email" VALUE="$value">|;

This results in form fields containing data from the previous request (or state). The CGI::Form object uses the param method from the CGI::Request module to retrieve the value for a specific form field.

print "<P>", "Snail Mail Address: ";
    print $form->textarea ('address', undef, 5, 40);

Here we create a textarea titled “address” with a size of 5 rows and 40 columns. The second argument to the textarea method is used for placing default information within a text area.

print "<P>", "What would you like to receive: ", "<BR>";
    print $form->checkbox_group (-name      => 'want',
                                 -values    => ['Latest Catalog',
                                              'Up-to-date Track News',
                                              'Catalog Specials'],
                                 -default   => 'Latest Catalog',
                                 -linebreak => 'true');

See how easy it is to create a group of checkboxes? The labels for each checkbox default to the specified values. However, you can pass a “-labels” argument if you want the labels to be different than the values.

print "<P>", "Where do you live: ", "<BR>";
print $form->radio_group (-name      => 'where',
                          -values    => ['North America',
                                         'South America',
                                         'Europe',
                                         'Australia',
                                         'Antartica'],
                           -default   => 'North America',
                           -linebreak => 'true');
print “<P>", “What type of events do you participate in: “, “<BR>";
print $form->popup_menu (-name    => 'events',
                            -values  => ['Sprints',
                                         'Middle Distance',
                                         'Distance',
                                         'Field Events',
                                         'Throws'],
                             -default => 'Sprints');

Radio buttons and popup menus are created in much the same way as checkboxes.

if ( ($form->param ('events') eq “Sprints") && ($form->param ('send_entry')) ) {
        if ($user) {
                warn “Shishir, $user is a sprinter!! Yahoo!\n";
            } else {
                warn “Shishir, we have an *anonymous* sprinter here!\n";
         }
    }

We use the param method to check the value of the events and send_entry fields. If our check is successful, we call the warn statement, which will output a message to the server log file in the following format:

[Mon Jan 29 15:07:25 1996] simple.pl: Shishir, Jan Apell is a sprinter!! Yahoo!

Now, let's finish off the program.

print “<P>";
    print $form->reset ();
    print $form->defaults ();
    print $form->submit ('send_entry', 'Submit');
    print $form->endform ();
}

The reset, defaults, and submit methods create different type of buttons. reset allows you to clear the values in the current form and display values from the previous state (or session). The defaults button clears the form entirely. And the submit method creates a Submit button for you to send the data to the server.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required