CGI and Perl

Example 1: Creating Forms with CGI.pm

The example in Listing 5.1 introduces the usage of CGI.pm in a typical script that generates and displays an HTML form. When run, the script parses the input from GET and POST methods, then prints the HTML output for a Web page with a form on it. If the script finds any data in the input stream (a previously filled-out form), it will be printed at the bottom of the page. The output is shown in Figure 5.3.

Note:

The line numbers in Listing 5.1 are for reference only and are not to be typed in.



Listing 5.1. Using CGI.pm with forms

1   #!/usr/local/bin/perl
 2   use CGI;
 3   $query = new CGI;
 4
 5   print $query->header;
 6
 7   print $query->start_html("Using CGI.pm with Forms");
 8   print "<H2> Example 1: Using CGI.pm with Forms</H2>
 9         <HR>\n";
 10
 11  &print_prompt($query);
 12  &do_work($query);
 13  print $query->end_html;
 14
 15  # Subroutines ###
 16
 17  sub print_prompt {
 18  my($query) = @_;
 19  print $query->start_multipart_form;
 20
 21  print "
 22  <table border=0 cellpadding=0 cellspacing=0 width=550>
 23  <tr><td>",
 24  $query->textfield(-name=>`first_name',
 25                    -default=>`John',
 26                    -size=>25),
 27  "<BR>First Name</td><td>",
 28  $query->textfield(-name=>`mi', -size=>2, -default=>`A'),
 29  "<BR>M.I.</td><td>",
 30  $query->textfield(-name=>`last_name',
 31                    -default=>`Doe',
 32                    -size=>25),
 33  "<BR>Last Name</tr></td>
 34  <tr><td colspan=3>",
 35  $query->textfield(-name=>`address', -size=>55),
 36  "<BR>Street Address</td></tr>
 37  <tr><td>",
 38  $query->textfield(-name=>`city',
 39                    -size=>25),
 40  "<BR>City</td><td>",
 41  $query->textfield(-name=>`state', -size=>2),
 42  "<BR>State</td><td>",
 43  $query->textfield(-name=>`zip',
 44                    -size=>10),
 45  "<BR>Zip Code</tr></td>
 46   </table>";
 47
 48  print "<HR><table border=0 cellspacing=0
 49              cellpadding=0 width=550>
 50        <tr><td><EM>What Operating Systems Do You Use?</EM>
 51        <BR>";
 52  print $query->checkbox_group(
 53         -name=>`Operating Systems',
 54         -values=>[Mac, `DOS', `SiliconGraphics IRIX', `NT 4.0'],
 55         -linebreak=>`yes',
 56         -defaults=>[`SiliconGraphics IRIX',Macintosh]);
 57
 58  print "</td><td><P><EM>What Platform is used most?</EM><BR>",
 59  $query->radio_group(
 60                     -name=>`platform',
 61                     -values=>[SiliconGraphics,Sun,Digital,Macintosh],
 62                     -linebreak=>`yes',
 63                     -default=>`SiliconGraphics');
 64
 65  print "</tr></td></table>";
 66  print "<HR><P><EM>How are you connected to the Internet?</EM><BR>";
 67  print $query->popup_menu(
 68        -name=>`Connection',
 69        -values=>[`ISDN','T-1','Direct Ethernet','Phone','Satellite'],
 70        -default=>`Phone');
 71
 72  print $query->hidden(`Hidden Reference','Bet you did not see me');
 73
 74  print "<P><EM>What Peripherals are
 75         connected to your computer?</EM><BR>";
 76  print $query->scrolling_list(
 77         -name=>`configuration',
 78         -values=>[`CDROM','Sound Card','Video Camera','3D Graphics'],
 79         -size=>4,
 80         -multiple=>`true');
 81
 82  print "<P><EM>What do you like about the World Wide Web?</EM><BR>";
 83  print $query->textarea(-name=>`Comments',
 84                         -rows=>8,
 85                         -columns=>60);
 86
 87  print "<p>";
 88  print $query->checkbox(`Add me to your mailing list');
 89  print "<P>",$query->reset;
 90  print $query->submit(`Action','Send Free Catalog');
 91  print $query->submit(`Action','No Free Catalog');
 92  print $query->endform;
 93  print "<HR>\n";
 94      }
 95
 96  sub do_work {
 97
 98  unless ($query->param) {
 99      print "<b>No query submitted yet.</b>";
 100     return;
 101     }
 102  my($query) = @_;
 103  my(@values,$key);
 104  print "<H2>Here are the current settings:</H2>";
 105  foreach $key ($query->param) {
 106     print "<b>$key</b> -> ";
 107     @values = $query->param($key);
 108     print join(", ",@values),"<BR>\n";
 109     }
 110  print "<HR></body></html>";
 111  }

Figure 5.3. The output from Example 1.

This program is a nice demonstration of using CGI.pm to generate a form and then using the variables entered by the user. Lines 1 and 2 define the script as Perl and include the CGI.pm module. Starting with line 4, CGI.pm is introduced into the script. Let's take a closer look at the different elements from CGI.pm used in this script. Parsing the Input Take a look at line 3:

$query = new CGI;

Line 3 calls the new() method of the CGI class. The new() method parses GET and POST method variables and all of the parameters from the input stream, does all URI decoding, and then stores the results as a new CGI object into the variable named $query. Yes, this one little line does all that. Though this sounds complicated, it greatly simplifies programming a CGI. You can now make simple method calls to this $query object to get environment variables, make forms, and do many other useful things. For example, in line 5, the $query->header method generates a
Content-type:
/text/html\n\n MIME header. In other words, by simply printing $query->header, CGI.pm interprets this statement and prints the default HTTP header for you. In fact, all of the HTML form elements in this example are generated in this way by calling methods such as $query->textfield(), $query->checkbox_group(), and $query->radio_group(), which take certain arguments and automatically generate all of the HTML that make up these HTML form elements. We'll take a look at the methods that automatically generate HTTP headers and HTML form elements next. Generating HTTP Headers If you recall from the beginning of the chapter, the first thing a CGI script must send back to the browser (especially a NPH CGI) is a Content-type header that describes the contents (MIME type) of the document that follows.

The $query->header() method returns the required Content-type: MIME header discussed earlier in this chapter. In line 5 of Example 1, $query->header() was called without any arguments, which caused it to default to text/html. Status codes and other HTTP headers can be passed
using the $query->header() method as well. Let's generate an HTTP header that returns a few different parameters. This requires that we give $query->header() a few different arguments. Passing multiple arguments to a function is quite simple; here's an example that generates an HTTP
response header with a MIME type and one of the status codes we discussed earlier in the chapter:

print $query->header(-type=>`/text/html',
                      -status=>`204 No Response');

If your CGI contained this line as the first thing it printed, a well-behaved browser such as Netscape should receive the 204 No Response header and do absolutely nothing.

If you wanted to use a redirect to send the browser to some other URL, a redirect() method exists to facilitate this:

print $query->redirect(`http://somewhere.else/');

Generating HTML Headers $query->start_html generates all necessary HTML headers to begin a web page, as demonstrated in line 7 of example 1.

print $query->start_html(-title=>`My Online Storefront,
                          -author=>`[email protected]',
                          -base=>`true',
                          -BGCOLOR=>"#ffffff"',
                  -NEWHEADER=>`whatever');

Adding additional HTML tags to this method is as easy as specifying them. For example, NEWHEADER in the preceding example could be anything. The base tag, if set to true, will resolve relative URLs in the document.

To end the HTML document, use the end_html() method:

print $query->end_html;

Generating HTML Form Elements

print $query->startform(-method=>$method,
                         -action=>$action,
                         -encoding=>$encoding);
 <... form stuff  ...>
 print $query->endform;

The defaults are

method: POST
 action: this script
 encoding: application/x-www-form-urlencoded

In all of the following methods that generate HTML form elements using CGI.pm, the field will be initialized with its previous contents from earlier invocations of the script. When the script is first called, or if the value was not set upon the last invocation, the field will have no value.

Many of the parameters for the following methods are identical. The -name parameter is a required parameter for all of the methods and has the same function in all methods except where noted. Parameters will be introduced only once unless their meaning changes in a particular method, in which case, the differences will be noted. Textfields $query->textfield()will return an HTML textfield form element, as demonstrated in several instances in lines 24-44 in example 1. The textfield() method accepts the following parameters:

print $query->textfield(-name=>`field_name',
                         -default=>`starting value',
                         -size=>50,
                         -maxlength=>80);
name The required name for the field.
default The default starting value for the field contents (optional).
size The size of the field in characters (optional).
maxlength The maximum number of characters the field will accept (optional).
Textareas $query->textarea()will return an HTML textarea form element, as demonstrated in lines 83-85 in Example 1. A textarea is similar to a textfield, but it allows you to specify rows and columns for a multiline text entry box. The starting value for the field can be long and contain multiple lines. The textfield() method accepts the following parameters:
print $query->textarea(-name=>`field_name',
                        -default=>`starting value',
                        -rows=>10,
                        -columns=>50);

-rows The height in number of lines of text the field will occupy.

-columns  The width in number of fixed-width characters the field will occupy.

Standalone Checkboxes $query->checkbox()will return an HTML checkbox form element, as demonstrated in line 88 in Example 1. The checkbox() method is used to create an isolated checkbox that isn't logically related to any other checkboxes. The checkbox() method accepts the following parameters:

print $query->checkbox(-name=>`checkbox_name',
                        -checked=>`checked',
                        -value=>`ON',
                        -label=>`CLICK ME');
-name In addition to being the required name for the checkbox, this value will also be used for the user-readable label printed next to the checkbox.
-checked Specifies that the checkbox is turned on by default (optional).
-value Specifies the value of the checkbox when it is checked. If not provided, the word on is assumed (optional).
-label The user-readable label to be attached to the checkbox. If not provided, the checkbox name is used (optional).

Checkbox Groups $query->checkbox_group() will return an HTML checkbox group form element, as demonstrated in lines 52-56 in Example 1. The checkbox_group() method creates a list of checkboxes that are related by the same name. The checkbox_group()method accepts the following parameters:

print $query->checkbox_group(-name=>`group_name',
                              -values=>[`eenie','meenie','minie','moe'],
                              -default=>[`eenie','moe'],
                              -linebreak=>`true',
                              -labels=>\%labels);
-values An array reference used for the user-readable labels printed next to the checkboxes as well as for the values passed to your script in the query string.
-default Can be either a reference to a list containing the values to be checked by default or can be a single value to be checked. If this argument is missing or undefined, then nothing is selected when the list first appears (optional).
-linebreak Can be set to true to place line breaks between the checkboxes so that they appear as a vertical list. Otherwise, they will be strung together on a horizontal line (optional).
-labels A pointer to an associative array relating the checkbox values to the user-visible labels that will be printed next to them. If not provided, the values will be used as the default (optional).

Radio Groups $query->radio_group() will return a radio button group, as demonstrated in lines 59-63 in Example 1. The radio_group() method creates a set of logically related radio buttons. Unlike the checkbox group, turning one member of the radio group on turns the others off. The only difference in the parameters between the radio_group and the checkbox_group is the -default parameter. The radio_group() method accepts the following parameters:

print $query->radio_group(-name=>`group_name',
   -values=>[`eenie','meenie','minie'],
                           -default=>`meenie',
                           -linebreak=>`true',
                           -labels=>\%labels);
-default The name of the default button to turn on. If not specified, the first item will be the default. You can provide a nonexistent button name such as -default =>`-' to start up with no buttons selected

Popup Menus $query->popup_menu() will return an HTML popup menu form element, as demonstrated in lines 67-70 in Example 1. The popup_menu() method creates an HTML menu the user can select from. The popup_menu() method accepts the following parameters:

print $query->popup_menu(-name=>`menu_name',
                          -values=>[`eenie','meenie','minie'],
                          -default=>`meenie',
                          -labels=>\%labels);
-default The name of the default menu choice. If not specified, the first item will be the default. The values of the previous choice will be maintained across queries.

Scrolling Lists $query->scrolling_list() will return an HTML scrolling list form element, as demonstrated in lines 76-80 in Example 1. The scrolling_list() method creates an HTML scrolling list. The scrolling_list() method accepts the following parameters:

print $query->scrolling_list(-name=>`list_name',
                              -values=>[`eenie','meenie','minie','moe'],
                              -default=>[`eenie','moe'],
                              -size=>5,
                              -multiple=>`true',
                              -labels=>\%labels);
-default Either a reference to a list containing the values to be selected by default or can be a single value to select. If this argument is missing or undefined, then nothing is selected when the list first appears optional).
-size The number of vertical rows to be displayed in the list (optional).
-multiple If set to true, allows multiple simultaneous selections; otherwise only one selection will be allowed at a time.

Hidden Fields $query->hidden() will return an invisible HTML form element, as demonstrated in line 72 in Example 1. The hidden() method produces a text field that can't be seen by the user. It is useful for passing state variable information from one invocation of the script to the next. The hidden() method accepts the following parameters:

print $query->hidden(-name=>`hidden_name',
                      -default=>[`value1','value2'...]);

Password Field $query->password_field() will return a password HTML form element. The password_field() method is identical to textfield(), except that its contents will be starred out on the Web page. The password_field() method accepts the following parameters:

print $query->password_field(-name=>`secret',
                              -value=>`starting value',
                              -size=>50,
                              -maxlength=>80);

Submit/Reset/Default Buttons $query->submit() will return the submit button form element, as demonstrated in lines 90 and 91 in Example 1. Every form should have one of these. The submit() method accepts the following parameters:

print $query->submit(-name=>`button_name',
                      -value=>`value');

$query->reset() will return the reset button form element, as demonstrated in line 89 in Example 1. The reset button restores the form to its values from the last time the script was called, not necessarily to the defaults. Every form should have one of these. The reset() method has no parameters:

print $query->reset

$query->defaults()will return a button that, when pressed, will cause the form to be completely reset to its defaults, wiping out all the changes the user ever made. The defaults() method accepts the following parameters:

print $query->defaults(`button_label')

Retrieving Data from HTML Form Fields When the form is processed, the value of the text field can be retrieved with

$value = $query->param(`field_name');

For fields that may contain multiple values, such as multiple selections from a scrolling list, an array can be returned:

@values = $query->param(`field_name');

If you want to change a field from its initial value after the script has been called once, you can do so like this:

$query->param(`field_name',"I'm the new value of field_name")

Likewise, an array of values could also be stored to a variable.