Chapter 8
Using Existing CGI Libraries
CONTENTS
Welcome to Hump Day in the afternoon. It really is a lovely day
outside, and every lesson series should have an early day off.
You should be able to read through this chapter relatively quickly
and catch your breath today. Expect to return to this chapter
on a regular basis, however, because it contains reference material
to what I think are some of the best CGI library resources available.
The Internet is a vast sea of resources. You can find almost anything
within the Internet Information sea, but how do you find the real
pearls in all those vast waters? Well, that's what you do in this
chapter-you examine a couple of Perl gems and one C library. They
will save you vast amounts of programming time. Make good use
of these libraries and don't be like the average programmer and
reinvent the wheel each time you build a new cart. Read through
the libraries to be sure you understand what they do and, with
cgi-lib.pl, how they do it.
Decide which library or libraries best suit your needs and then
download them from the resources identified. Usually, you will
want to install them in your cgi-bin
directory. Make sure that you check with your Webmaster to see
whether these libraries already are installed on your server.
Be lazy like me, and make good use of these libraries so that
you can concentrate on whatever is today's real problem. And that's
what this afternoon's lesson is about. In this chapter, you will
learn about several existing libraries on the Net.
In particular, you will learn about the following:
- cgi-lib.pl:
A nice, compact library for performing simple CGI operations.
- CGI.pm: A
robust Perl 5 library for reading CGI data, saving the state of
your program, generating HTML Web fill-out forms, and generating
other basic HTML tags.
- cgic: An
ANSI C CGI library for decoding incoming CGI data.
The cgi-lib.pl version 1.14
library is the smallest library you will learn about in this chapter.
Don't discard it from your toolbox just because it is small, though.
Many of your CGI programs will be small applications that don't
require a large library with a large amount of code to interpret.
Some of the advantages of a small library are ease of understanding,
ease of use, and improved efficiency. The smaller cgi-lib.pl
library also takes less time to load than the other, larger libraries.
I particularly like the cgi-lib.pl
library because of its simplicity. For lots of small applications,
it's just perfect. The cgi-lib.pl
library is written and copyrighted by Steven E. Brenner (S.E.Brenner@bioc.cam.ac.uk)
and is included here with his permission. You can find the latest
copy of this library at
http://www.bio.cam.ac.uk/web/form.asp
As you look through this library, take a close look at the first
few lines of the PrintVariables
function. Steve uses the special Perl global variable $*.
The $* variable enables multiple-line
pattern matching. But in addition to that, Steve illustrates good
programming practice by saving the value of the $*
variable before his subroutine changes it for its own use. This
way, before his subroutine exits, it can restore the original
value of the $* variable.
Saving the values of any variables you need to use inside your
subroutines and then restoring them before you exit the subroutine
saves you many hours hunting for strange and hard-to-find bugs.
This means that you can go out and party at night instead of having
an all-night affair with your computer.
The MethGet function determines
which HTTP request method was used to call your CGI program. The
function returns True if
the request method was Get.
The complete function is only one statement long. Sometimes it
seems silly or not worth the effort to create a function that
is only a couple of lines long. If you are going to use the same
code several times, however, it makes sense to make that code
into a subroutine. I like to use the three-or-greater rule: If
the same code is going to be used in three or more places, it
should be made into a subroutine. Listing 8.1 shows the MethGet
function in its entirety.
Listing 8.1. The MethGet
function.
1: sub MethGet {
2: return ($ENV{'REQUEST_METHOD'} eq "GET");
3: }
The ReadParse() function
reads in Get or Post
data, converts it to unescaped text, and puts one key=value
in each member of the list @in.
The ReadParse function also
creates key/value pairs in %in,
using '\0' to separate multiple
selections. If a parameter (*cgi_input,
for example) is passed to ReadParse,
the parsed data is stored there, rather than in $in,
@in, and %in.
Listing 8.2 shows the ReadParse
function.
Listing 8.2. The ReadParse
function.
01: sub ReadParse {
02: local (*in) = @_ if @_;
03: local ($i, $loc, $key, $val);
04: # Read in text
05: if ($ENV{'REQUEST_METHOD'} eq "GET") {
06: $in = $ENV{'QUERY_STRING'};
07: } elsif ($ENV{'REQUEST_METHOD'} eq "POST") {
08: read(STDIN,$in,$ENV{'CONTENT_LENGTH'});
09: }
10: @in = split(/&/,$in);
11:
12: foreach $i (0 .. $#in) {
13: # Convert pluses to spaces
14: $in[$i] =~ s/\+/ /g;
15: # Split into key and value.
16: ($key, $val) = split(/=/,$in[$i],2); # splits on the first =.
17: # Convert %XX from HEX numbers to alphanumeric
18: $key =~ s/%(..)/pack("c",hex($1))/ge;
19: $val =~ s/%(..)/pack("c",hex($1))/ge;
20: # Associate key and value
21: $in{$key} .= "\0" if (defined($in{$key}));
# \0 is the multiple separator
22: $in{$key} .= $val;
23: }
24: return 1; # just for fun
25: }
The function PrintHeader
returns the content-type: text/html
HTTP response header for HTML documents with the correct number
of newline characters (\n\n).
Listing 8.3 shows the PrintHeader
function.
Listing 8.3. The PrintHeader
function.
1: sub PrintHeader {
2: return "content-type: text/html\n\n";
3: }
The function PrintVariables,
shown in Listing 8.4, formats an input variable list that is an
associative array and returns an HTML string formatted as a definition
list (<DL>) made up
of the keyword represented as a definition term (<DT>)
and the keyword value as a definition description (<DD>).
Listing 8.4. The PrintVariables
function.
01: sub PrintVariables {
02: local (%in) = @_;
03: local ($old, $out, $output);
04: $old = $*; $* =1;
05: $output .= "<DL COMPACT>";
06: foreach $key (sort keys(%in)) {
07: foreach (split("\0", $in{$key})) {
08: ($out = $_) =~ s/\n/<BR>/g;
09: $output .= "<DT><B>$key</B><DD><I>$out</I><BR>";
10: }
11: }
12: $output .= "</DL>";
13: $* = $old;
14: return $output;
15: }
The function PrintVariablesShort,
shown in Listing 8.5, formats an input variable list
that is an associative array and returns an HTML string formatted
as one line per keyword/value pair.
Listing 8.5. The PrintVariablesShort
function.
01: sub PrintVariablesShort {
02: local (%in) = @_;
03: local ($old, $out, $output);
04: $old = $*; $* =1;
05: foreach $key (sort keys(%in)) {
06: foreach (split("\0", $in{$key})) {
07: ($out = $_) =~ s/\n/<BR>/g;
08: $output .= "<B>$key</B> is <I>$out</I><BR>";
09: }
10: }
11: $* = $old;
12: return $output;
13: }
The Perl 5 library CGI.pm
uses objects to create Web forms on-the-fly and to parse their
contents. It is similar to cgi-lib.pl
in some respects. Perl 5 is an object-oriented version of the
standard Perl language. It provides a simple interface for parsing
and interpreting query strings passed to CGI scripts. It also
offers a rich set of functions for creating fill-out forms, however.
Instead of remembering the syntax for HTML form elements, you
just make a series of Perl function calls. An important fringe
benefit of this is that the value of the previous query is used
to initialize the form, so the state of the form is preserved
from invocation to invocation. The CGI.pm
library is included in this chapter with the permission of Mr.
Lincoln Stein, MD, Ph.D. and is available at
http://www-genome.wi.mit.edu/WWW/tools/scripting/CGIperl
Everything is done through a CGI object. When you create one of
these objects, it examines the environment for a query
string, parses it, and stores the results. You then can ask the
CGI object to return or modify the query values. CGI objects handle
Post and Get
methods and distinguish between scripts called from Isindex
documents and form-based documents. In fact, you can debug your
script from the command line without worrying about setting up
environment variables.
A script to create a fill-out form that remembers its state each
time it's invoked is very easy to write with CGI.pm.
Listing 8.6 shows an example of such a script.
Listing 8.6. Creating a fill-out form using CGI.pm.
01: use CGI;
02: $query = new CGI;
03: print $query->header;
04:
05: print $query->startform;
06: print "What's your name? ",$query->textfield('name');
07: print "<P>What's the combination? ",
08: $query->checkbox_group('words',['eenie','meenie','minie','moe']);
09: print "<P>What's your favorite color? ",
10: $query->popup_menu('color',['red','green','blue','chartreuse']);
11: print "<P>",$query->submit;
12: print $query->endform;
13:
14: print "<HR>\n";
15: if ($query->param) {
16: print "Your name is <EM>",$query->param('name'),"</EM>\n";
17: print "<P>The keywords are: <EM>",join(", ",$query->param('words')),
"</EM>\n";
18: print "<P>Your favorite color is <EM>",$query->param('color'),"</EM>\n";
19: }
To use this package, install it in your Perl library path. On
most systems, this will be /usr/local/lib/perl5,
but check with your System Administrator to be sure. Then place
the following statement at the top of your Perl CGI scripts:
Use CGI;
If you do not have sufficient privileges to install into /usr/local/lib/perl5,
you still can use CGI.pm.
Place it in a convenient place-for example, in
/usr/local/etc/httpd/cgi-bin-and preface your CGI
scripts with a preamble something like this:
BEGIN {
push(@Inc,'/usr/local/etc/httpd/cgi-bin');
}
Use CGI;
Be sure to replace /usr/local/etc/httpd/cgi-bin
with the location of CGI.pm
on your server.
You can use two methods in the CGI.pm
library to read data passed to your CGI program:
- $query = new CGI;
This method parses the input (from both Post
and Get methods) and stores
it in a Perl 5 object called $query.
- $query = new CGI(FILEHANDLE);
This method enables you to read the contents of the
form from a previously opened filehandle.
The filehandle can contain a URL-encoded query
string, or it can be a series of newline delimited tag=value
pairs. This method is compatible with the save()
method, which enables you to save the state of a form to a file
and reload it later.
Your incoming data should be saved to an object such as the $query
object. The following methods are available for decoding and modifying
the object data; these methods assume that you have named that
object $query.
Getting a List of Keywords from the Query Object
If your CGI program was invoked as the result of an Isindex
search, the parsed keywords of the Isindex
input search string can be obtained with the keywords()
method. This method returns the keywords as a Perl array. Use
this code:
@keywords = $query->keywords
Getting the Names of All Parameters Passed to Your Script
If your CGI program was invoked with a parameter list such as
name1=value1&name2=value2&name3=value3"
the param() method returns
the parameter names as a list. For backward compatibility, this
method works even if the script was invoked as an Isindex
script; in this case, a single parameter name is returned named
'keywords'. Use this code:
@names = $query->param
Getting the Value(s) of a Named Parameter
You pass the param('NAME')
method a single argument to fetch the value of the named parameter.
If the parameter is multivalued (from multiple selections in a
scrolling list, for example), you can ask to receive an array.
Otherwise, the method returns a single value. Use this code:
@values = $query->param('foo');
or
$value = $query->param('foo');
As of version 1.50 of this library, the array of parameter names
returned is in the same order in which the browser sent them.
Although this is not guaranteed to be identical to the order in
which the parameters were defined in the fill-out form, this is
usually the case.
Setting the Value(s) of a Named Parameter
The method
param('NAME' 'NEW-VALUES')
sets the value for the named parameter 'foo'
to one or more values. These values are used to initialize form
elements, if you so desire. Note that this is the correct way
to change the value of a form field from its current setting.
Use this code:
$query->param('foo','an','array','of','values');
Deleting a Named Parameter
The method
delete('NAME')
deletes a named parameter entirely. This is useful when you want
to reset the value of the parameter so that it isn't passed down
between invocations of the script. Use this code:
$query->delete('foo');
Importing Parameters into a Namespace
The method
import_names('NAME_SPACE')
imports all parameters into the given namespace. If there were
parameters named 'foo1',
'foo2', and 'foo3',
for example, after executing $query->import('R'),
the variables @R::foo1, $R::foo1,
@R::foo2, $R::foo2,
and so on would conveniently spring into existence. Because CGI
has no way of knowing whether you expect a multi- or single-valued
parameter, it creates two variables for each parameter. One variable
is an array and contains all the values, and the other is a scalar
containing the first member of the array. Use whichever variable
is appropriate. For keyword (a+b+c+d) lists, the variable @R::keywords
is created. Use this code:
$query->import_names('R')
If you don't specify a namespace, this method assumes namespace
"Q". Use this code:
$query->import_names('R');
print "Your name is $R::name\n"
print "Your favorite colors are @R::colors\n";
| Warning |
|
Do not import into namespace 'main'. This represents a major security risk, because evil people then could use this feature to redefine central variables such as @Inc. If you try to do this, CGI.pm exits with an error.
|
As you have seen throughout this guide, saving the state of your
CGI program is one of the harder things to do in the CGI environment.
The CGI.pm library addresses
that need with the following two methods. These two methods enable
you to save object state information so that you can use it the
next time your CGI program is called.
Saving the State to a File
The method
save(FILEHANDLE)
writes the current query object out to the filehandle of your
choice. The filehandle already must be open and writable but,
other than that, it can point to a file, a socket, a pipe, or
whatever. The contents of the form are written out as tag=value
pairs, which can be reloaded with the new()
method later. Use this code:
$query->save(FILEHANDLE)
Saving the State in a Self-Referencing URL
The method
self_url()
returns a URL that, when selected, reinvokes your CGI program
with all its state information intact. This is most useful when
you want to jump around within a script-generated document using
internal anchors but don't want to disrupt the current contents
of the form(s). Use this code:
$my_url=$query->self_url;
Every CGI program needs to print the correct HTTP headers. The
following methods perform this task for you with a minimum amount
of programming effort.
Creating the Standard Header for a Virtual Document
The header('CONTENT-TYPE/SUBTYPE')
method prints the required HTTP content-type
header and the requisite blank line below it. If no parameter
is specified, it defaults to 'text/html'.
Use this code:
print $query->header('image/gif');
An extended form of this method enables you to specify a status
code and a message to pass back to the browser. Use this code:
print $query->header('text/html',204,'No response');
This method presents the browser with a status code of 204 (no
response). Properly behaved browsers will take no action and simply
remain on the current page. (This is appropriate for a script
that does some processing but doesn't need to display any results,
or for a script called after a user clicks on an empty part of
a clickable imagemap.)
Creating the Header for a Redirection Request
The method
redirect('Absolute-URI')
generates a redirection request for the remote browser. It immediately
goes to the indicated URI. Your CGI program should exit soon after
this. Nothing else is displayed. Use this code:
print $query->redirect('http://somewhere.else/in/the/world');
The method
start_html('TITLE', 'EMAIL-ADDRESS', 'BASE-TAG','ATTRIBUTE-LIST')
generates the header tags for your HTML page. The input parameters
are the title, your e-mail address, the Base
tag, and an arbitrary list of attributes, such as the background
color or keywords. The method returns a canned HTML header and
the opening Body tag. Use
this code:
print $query->start_html('Secrets of the Pyramids',
'fred@capricorn.org',
'true',
'BGCOLOR="#00A0A0"')
Table 8.1 explains the parameters of the start_html
method; these are optional.
Table 8.1. The start_html
parameters.
| Name | Meaning
|
| TITLE |
The title string to use for the HTML header. |
| EMAIL-ADDRESS
| The author's e-mail address (creates a <LINK REV="MADE"> tag).
|
| BASE-TAG
| Set to True if you want to include a Base tag in the header. This helps resolve relative addresses to absolute ones when the document is moved but makes the document hierarchy non-portable. Use this with care!
|
| ATTRIBUTE-LIST
| Any additional attributes you want to incorporate into the Head tag (as many as you want). This is a good way to incorporate Netscape-specific extensions, such as a background color and a wallpaper pattern. (The example in this
section sets the page background to a vibrant blue.)
|
The end_html method ends
an HTML document by printing the </BODY></HTML>
tags. Use this code:
print $query->end_html
The CGI.pm library provides
a full set of methods for creating Web fill-out forms. The various
form-creating methods all return strings to the caller. These
strings contain the HTML code that creates the requested form
element. You are responsible for actually printing these strings.
It's set up this way so that you can place formatting tags around
the form elements.
The default values that you specify for the forms are used only
the first time the script is invoked. If values already are present
in the query string, they
are used, even if blank. If you want to change the value of a
field from its previous value, call the param()
method to set it.
To reset the fields to their defaults, you can do this:
- Create a special <VAR>defaults</VAR>
button using the defaults()
method.
- Create a hypertext link that calls your script without any
parameters.
The optional values of the Web fill-out form methods depend on
their positions in the parameter list. You cannot leave out value
two of a four-value parameter list and include values three and
four, for example. If you want to include any value in a parameter
list that is to the right of another optional parameter, you must
include the earlier parameter, even if you want the default value
from the earlier parameter.
You can put multiple forms on the same page if you want. Be warned
that it isn't always easy to preserve state information for more
than one form at a time, however.
By popular demand, the text and labels you provide for form elements
are escaped according to HTML rules. This means that you can safely
use "<CLICK ME>"
as the label for a button. However, this behavior might interfere
with the capability to incorporate special HTML character sequences-such
as &Aacute; (Á)-into
your fields. If you want to turn off automatic escaping, call
the autoEscape() method with
a False value immediately
after creating the CGI object, as outlined in this program fragment:
$query = new CGI;
$query->autoEscape(undef);
You can turn autoescaping back on at any time with
$query->autoEscape('yes')
Creating an Isindex Tag
The isindex() method called
without any arguments returns an Isindex
tag that designates your CGI program as the URI to call. If you
want the browser to call a different URI to handle the search,
pass isindex('TGT-URI') the
URI you want to be called. Use this code:
print $query->isindex($action);
Starting a Form
The method
startform('HTTP-METHOD', 'TGT-URI')
returns a Form tag with the
optional HTTP-METHOD and
TGT-URI that you specify
(Post and none assumed).
Use this code:
print $query->startform($method,$action);
Table 8.2 explains the parameters of the startform()
function.
Table 8.2. The startform()
parameters.
| Name | Meaning
|
| HTTP-METHOD
| The method the data sends to the server; it can be Get or Post. If this field is not supplied, the default method is Post.
|
| TGT-URI
| The CGI program to invoke when the Web fill-out form is sent to the server. If this field is not supplied, the default is none.
|
Ending a Form
The endform() method returns
a Form tag. Use this code:
print $query->endform;
Creating a Text Field
The method
textfield('NAME','INITIAL-VALUE','WINDOW-SIZE','MAX-chARACTERS')
returns a string that contains the HTML code for a text-input
field. Use this code:
print $query->textfield('foo','starting value',50,80);
Table 8.3 explains the parameters of the textfield()
function.
Table 8.3. The textfield()
parameters.
| Name | Meaning
|
| INITIAL-VALUE
| Initial value for the text-field contents. This parameter is optional.
|
| MAX-chARACTERS
| Maximum number of characters the field accommodates. This parameter is optional.
|
| NAME |
Name field. This parameter is required.
|
| WINDOW-SIZE
| Size of the text-entry window, in characters. This parameter is optional.
|
As with all these methods, the field is initialized with its contents
from earlier invocations of the script. When the form is processed,
the value of the Text field
can be retrieved with this code:
$value = $query->param('foo');
Creating a Textarea Field
The method
textarea('NAME','INITIAL-VALUE','ROWS','COLUMNS')
is just like the textfield()
method, but it enables you to specify rows and columns for a multiline
text-entry box. You can provide a starting value for the field,
which can be long and contain multiple lines. Scrollbars for both
horizontal and vertical scrolling are added automatically. Use
this code:
print $query->textarea('foo','starting value',50,80);
Table 8.4 explains the parameters of the textarea()
function.
Table 8.4. The textarea()
parameters.
| Name | Meaning
|
| COLUMNS
| Number of columns of the text area window. This parameter is optional.
|
| INITIAL-VALUE
| Initial value for the text-area contents. This can be multiple lines. This parameter is optional.
|
| NAME |
Text-area Name field. This parameter is required.
|
| ROWS |
Number of rows of the text-area window. This parameter is optional.
|
Creating a Password Field
The method
password_field('NAME', 'INITIAL-VALUE', 'WINDOW-SIZE','MAX-chARACTERS')
is identical to textfield()
except that its contents, when typed from the keyboard or from
the Value field, are represented
by asterisks on the Web page. Use this code:
print $query->password_field('foo','starting value',50,80);
Table 8.5 explains the parameters of the password_field()
function.
Table 8.5. The password_field()
parameters.
| Name | Meaning
|
| INITIAL-VALUE
| Initial value for the Password field's contents. This parameter is optional.
|
| MAX-chARACTERS
| Maximum number of characters the field accommodates. This parameter is optional.
|
| NAME |
Password Name field. This parameter is required.
|
| WINDOW-SIZE
| Size of the text-entry window, in characters. This parameter is optional.
|
Creating a Pop-Up Menu
The method
popup_menu('NAME', 'OPTION-NAMES', 'SELECTED-OPTION', 'OPTION-VALUES')
creates a selection menu, which also is referred to as a pull-down menu. Use this code:
print $query->popup_menu('menu_name',['eenie','meenie','minie'],'meenie');
or
print $query->popup_menu('menu_name',
['one','two','three'],'two',
{'one'=>'eenie','two'=>'meenie','three'=>'minie'});
Table 8.6 explains the parameters of the popup_menu()
function.
Table 8.6. The popup_menu()
parameters.
| Name | Meaning
|
| NAME |
Pop-up menu Name field. This parameter is required.
|
| OPTION-NAMES
| An array reference containing the list of menu items in the menu. You can pass the method an anonymous array, as shown in the example, or a reference to a named array, such as @foo. This parameter is required.
|
| OPTION-VALUES
| An array reference to an associative array containing user-visible labels for one or more of the menu items. You can use this when you want the user to see one menu string but have the browser return to your program a different string.
Because this is an associative array and you must match the OPTION-NAMES with the OPTION-VALUES, the order of the associative array is not important. If this value is undefined, the OPTION-NAMES are sent as the
OPTION-VALUES to your CGI program. This parameter is optional.
|
| SELECTED-OPTION
| Name of the default menu choice. If not specified, the first item is the default. The value of the previous choice is maintained across queries. This parameter is optional.
|
When the form is processed, the selected value of the pop-up menu
can be retrieved by using this code:
$popup_menu_value = $query->param('menu_name');
Creating a Scrolling List
The method
scrolling_list('NAME', 'OPTION-NAMES', 'SELECTED-OPTIONS', 'LIST-SIZE',
'MULTIPLE-SELECTIONS', 'OPTION-VALUES')
creates a scrolling list that contains the items passed in the
OPTION-NAMES parameter. The
list can be set to select only one item or multiple items at a
time. Use this code:
print $query->scrolling_list('list_name',
['eenie','meenie','minie','moe'],
['eenie','moe'],5,'true');
or
print $query->scrolling_list('list_name',
['one','two','three','four'],
['one','four'],5,'true',
{'one'=>'eenie','two'=>'meenie',
'three'=>'minie','four'=>'moe'});
Table 8.7 explains the parameters of the scrolling_list()
function.
Table 8.7. The scrolling_list()
parameters.
| Name | Meaning
|
| LIST-SIZE
| Number of visible list items. If undefined, the default is 1. This parameter is optional.
|
| MULTIPLE-SELECTIONS
| If True, multiple simultaneous selections are allowed. If undefined, only one selection is allowed at a time. This parameter is optional.
|
| NAME |
Scrolling-list Name field. This parameter is required.
|
| OPTION-NAMES
| An array reference containing the list of menu items in the menu. You can pass the method an anonymous array, as shown in the example, or a reference to a named array, such as @foo. This parameter is required.
|
| OPTION-VALUES
| An array reference to an associative array containing user-visible labels for one or more of the menu items. You can use this when you want the user to see one menu string but have the browser return to your program a different string.
Because this is an associative array and you must match the OPTION-NAMES with the OPTION-VALUES, the order of the associative array is not important. If this value is undefined, the OPTION-NAMES are sent as the
OPTION-VALUES to your CGI program. This parameter is optional.
|
| SELECTED-OPTIONS
| A reference to a list containing the values to be selected by default or a single value to select. If this argument is missing or undefined, nothing is selected when the list first appears. This parameter is optional.
|
When this form is processed, all selected list items are returned
as a list under the parameter name 'list_name'.
You can retrieve the values of the selected items with this code:
@selected = $query->param('list_name');
Creating a Group of Related Checkboxes
The method
checkbox_group('GROUP-NAME', 'BOX-NAMES', 'SELECTED-LIST', 'VERTICAL',
'BOX-VALUES')
creates a list of checkboxes that are related by the same name,
just as pop-up menus and scrolled lists are related by the same
name. Use this code:
print $query->checkbox_group('group_name',
['eenie','meenie','minie','moe'],
['eenie','moe'],'true');
or
print $query->checkbox_group('group_name',
['one','two','three','four'],
['one','two'],'true',
{'one'=>'eenie','two'=>'meenie',
'three'=>'minie','four'=>'moe'});
Table 8.8 explains the parameters of the checkbox_group().
Table 8.8. The checkbox_group()
parameters.
| Name | Meaning
|
| BOX-NAMES
| An array reference to the names 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. This parameter is required.
|
| BOX-VALUES
| An array reference to an associative array containing user-visible labels for one or more of the checkbox items. You can use this when you want the user to see one visible string but have the browser return a different string to your
program. Because this is an associative array, and you must match the OPTION-NAMES with the OPTION-VALUES, the order of the associative array is not important. If this value is undefined, the OPTION-NAMES are sent as the
OPTION-VALUES to your CGI program. This parameter is optional.
|
| GROUP-NAME
| The checkbox group_name field. This parameter is required.
|
| SELECTED-LIST
| Either a reference to a list containing the values to be checked by default or a single value to be checked. If this argument is missing or undefined, nothing is selected when the list appears. This parameter is optional.
|
| VERTICAL
| If True, places line breaks between the checkboxes so that they appear as a vertical list. If this argument is undefined or False, the checkboxes are strung together on a horizontal line. This parameter is optional.
|
You can retrieve the values of the enabled checkboxes (those that
are turned on) with this code:
@turned_on = $query->param('group_name');
Creating a Standalone Checkbox
The method
checkbox('NAME', 'SELECTED', 'CGI-VALUE', 'VALUE')
is used to create an isolated checkbox that isn't logically related
to any others. Use this code:
print $query->checkbox('checkbox_name',1,'TURNED ON','Turn me on');
Table 8.9 explains the parameters of the checkbox()
function.
Table 8.9. The checkbox()
parameters.
| Name | Meaning
|
| CGI-VALUE
| The value passed to your CGI program when the checkbox is selected. If not provided, the word on is assumed. This parameter is optional.
|
| NAME |
The checkbox Name field. This parameter is required.
|
| SELECTED
| If True, the checkbox is selected. If the argument is missing or undefined, the checkbox is not selected. This parameter is optional.
|
| VALUE |
Assigns a user-visible label to the button. If not provided, the checkbox's name is used. This parameter is optional.
|
You can retrieve the value of the checkbox by using this code:
$turned_on = $query->param('checkbox_name');
Creating a Radio Button Group
The method
radio_group('GROUP-NAME', 'BUTTON-NAMES','SELECTED','VERTICAL','BUTTON-VALUES')
creates a set of logically related radio buttons. Turning on one
member of the group turns off the others. Use this code:
print $query->radio_group('group_name',['eenie','meenie','minie'],
'meenie','true');
or
print $query->radio_group('group_name',['one','two','three'],
'two','true',
{'one'=>'eenie','two'=>'meenie'});
Table 8.10 explains the parameters of the radio_group()
function.
Table 8.10. The radio_group()
parameters.
| Name | Meaning
|
| BUTTON-NAMES
| An array reference to the names used for the user-readable labels printed next to the radio buttons, as well as for the values passed to your script in the query string. This parameter is required.
|
| BUTTON-VALUES
| An array reference to an associative array containing user-visible labels for one or more of the radio button items. You can use this when you want the user to see one visible string but have the browser return a different string to your
program. Because this is an associative array and you must match the OPTION-NAMES with the OPTION-VALUES, the order of the associative array is not important. If this value is undefined, the OPTION-NAMES are sent as the
OPTION-VALUES to your CGI program. This parameter is optional.
|
| GROUP-NAME
| The radio button group_name field. This parameter is required.
|
| SELECTED
| Name of the default button to turn on. If not specified, the first item is the default. Specify the minus sign (-) if you don't want any button to be turned on. This parameter is optional.
|
| VERTICAL
| If True, places line breaks between the radio buttons so that they appear as a vertical list. If this argument is undefined or False, the radio buttons are strung together on a horizontal line.
|
When the form is processed, you can retrieve the selected radio
button by using this code:
$which_radio_button = $query->param('group_name');
The method
submit('NAME', 'VALUE')
creates the Query Submission button. Every Web fill-out form that
has more than one text-entry field or any other input type should
have a Submit button. Use this code:
print $query->submit('button_name','value');
Table 8.11 explains the parameters of the submit()
function.
Table 8.11. The submit()
parameters.
| Name | Meaning
|
| NAME |
You can give the button a name if you have several submission buttons on your form and you want to distinguish between them. The name also is used as the user-visible label. This parameter is optional.
|
| VALUE |
This gives the button a value that is passed to your script in the query string. You can figure out which button was pressed by using different values for each button. This parameter is optional.
|
You can retrieve the value of the Submit button by using this
code:
$which_one = $query->param('button_name');
The method
reset('LABEL')
creates the Reset button. It undoes whatever changes the user
has recently made to the form, but it does not necessarily reset
the form all the way to the defaults. (See the next section, "Creating
a Defaults Button," for that.) This method takes an optional
LABEL argument. If set, LABEL
defines the visible name of the Reset button, which is Reset
by default. Use this code:
print $query->reset
The defaults('LABEL') method
creates a Reset to Defaults button. It takes the optional label
for the button, which is Default
by default. When the user clicks this button, the form is set
to the defaults you specify in your script, just as it was the
first time it was called. Use this code:
print $query->defaults('button_label')
The method
hidden('NAME', VALUE(1), ... VALUE(N))
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. Use this code:
print $query->hidden('hidden_name','hidden_value1','hidden_value2'...);
Table 8.12 explains the parameters of the hidden()
function.
Table 8.12. The hidden()
parameters.
| Name | Meaning
|
| NAME |
The name of the hidden field. This parameter is required.
|
| VALUE |
The second and subsequent arguments specify the value for the hidden field.
|
The hidden() method is a
quick-and-dirty way of passing Perl arrays through forms
| Note |
|
As of version 1.52, the default values always override the current values in hidden variables. This is different from the behavior of all the other form fields, where the current value overrides the default value, but it seems to be the way that people
expect things to work.
|
You can retrieve the value of a hidden field with this code:
$hidden_value = $query->param('hidden_name');
Or, for values created with arrays, you can use this code:
@hidden_values = $query->param('hidden_name');
The method
image_button('NAME', 'SRC', 'ALIGN')
produces an inline image that acts as a Submission button. When
selected, the form is submitted and the clicked (x,y) coordinates
are submitted as well. Use this code:
print $query->image_button('button_name','/source/URL','MIDDLE');
Table 8.13 explains the parameters of the image_button()
function.
Table 8.13. The image_button()
parameters.
| Name | Meaning
|
| ALIGN |
Alignment option: TOP, BOTTOM, or MIDDLE. This parameter is optional.
|
| NAME |
Name of the image button. This parameter is required.
|
| SRC |
Specifies the URI of the image to display. It must be one of the types supported by inline images (GIF, for example) but can be any local or remote URI. This parameter is required.
|
After the image is clicked, the results are passed to your script
in two parameters named "button_name.x"
and "button_name.y",
where "button_name"
is the name of the image button:
$x = $query->param('button_name.x');
$y = $query->param('button_name.y');
By default, if you use a special HTML character-such as >,
<, or &-as
the label or value of a button, it is escaped using the appropriate
HTML escape sequence (for example, &gt;).
This process enables you to use anything at all for the text of
a form field without worrying about breaking the HTML document.
However, it also might interfere with the capability to use special
characters-such as Á-as
the default contents of fields. You can turn this feature on and
off with the method autoEscape('ON/OFF'),
as shown in this code:
$query->autoEscape(undef); turns automatic HTML escaping OFF.
$query->autoEscape('true'); turns automatic HTML escaping ON.
cgic is an ANSI C-language
library for the creation of CGI-based World Wide Web applications.
cgic is included in this
chapter with the permission of Thomas Boutell (<boutell@boutell.com>),
and can be found at
http://sunsite.unc.edu/boutell/cgic/
cgic performs these tasks:
- Parsing form data, correcting for defective or inconsistent
browsers
- Transparently accepting both Get
and Post form data
- Handling line breaks in form fields in a consistent manner
- Providing string, integer, floating-point, and single- and
multiple-choice functions to retrieve form data
- Providing bounds-checking for numeric fields
- Loading CGI environment variables into C strings that are
always non-null
- Providing a way to capture CGI situations for replay in a
debugging environment
- Providing a somewhat safer form of the system()
function
cgic should be compatible
with any CGI-compliant server environment.
| Note |
|
All cgic applications must be linked to the cgic.c module itself. How you do this depends on your operating system; under UNIX, just use the provided makefile as an example.
|
Because all CGI applications must perform certain initial tasks,
such as parsing form data and examining environment variables,
the cgic library provides
its own main() function.
When you write applications that use cgic,
you begin your own programs by writing a cgiMain()
function, which cgic invokes
when the initial CGI work has been completed successfully. Your
program also must be sure to include the file cgic.h.
| Warning |
|
If you write your own main() function, your program will not link properly. Your own code should begin with cgiMain(). The library provides main() for you.
|
You can use this section as a quick-and-easy reference to learn
about the various string functions.
cgiFormString
The cgiFormString() function
retrieves the first argument (name)
from the Web fill-out form and places the retrieved value into
the result. Use this code:
cgiFormResultType cgiFormString(char *name, char *result, int max)
Table 8.14 explains the parameters of the cgiFormString
function.
Table 8.14. The cgiFormString
parameters.
| Argument | Meaning
|
| max |
Maximum size of the result buffer. This size always should be one greater than the expected size of the input buffer, because a terminating null character is added to all result fields.
|
| *name |
Name of the input field in the form. Usually, this is the Name attribute of the Web fill-out form input type.
|
| *result
| Buffer for the requested form name. The text is copied into the buffer specified by result, up to but not exceeding max-1 bytes. A terminating null character then is added to complete the string.
|
Regardless of the newline format submitted by the browser, cgiFormString()
always encodes each newline as a single line feed (ASCII decimal
10). As a result, the final string may be slightly shorter than
indicated by a call to cgiFormStringSpaceNeeded
but will never be longer.
cgiFormString() returns one
of these status codes:
- cgiFormEmpty:
The string was retrieved but was empty.
- cgiFormLong:
The string was retrieved but was truncated to fit the buffer.
- cgiFormNotFound:
No such input field was submitted. In this case, an empty string
is copied to result.
- cgiFormSuccess:
The string was retrieved successfully.
- cgiFormTruncated:
The string was retrieved but was truncated to fit the buffer.
cgiFormStringMultiple
The cgiFormStringMultiple()
function is useful in the unusual case in which several input
elements in the form have the same name and, for whatever reason,
the programmer does not want to use the checkbox, radio button,
and selection menu functions. This is needed occasionally if the
programmer cannot know in advance what values might appear in
a multiple-selection list or group of checkboxes on a form. The
value pointed to by the result is set to a pointer to an array
of strings; the last entry in the array is a null pointer. This
array is allocated by the CGI library. Use this code:
cgiFormResultType cgiFormStringMultiple(char *name, char ***ptrToStringArray)
Table 8.15 explains the parameters of the cgiFormStringMultiple()
function.
Table 8.15. The cgiFormStringMultiple()
parameters.
| Argument | Meaning
|
| *name |
Name of the input field in the form. Usually, this is the Name attribute of the Web fill-out form input type; in this case, multiple fields with the same name value are expected.
|
| ***ptrToStringArray
| A pointer to an array of string pointers. This is the list of retrieved names. In all cases except when out of memory, ptrToStringArray is set to point to a valid array of strings, with the last element in the array being a null
pointer; in the out-of-memory case, ptrToStringArray is set to a null pointer.
|
| Warning |
|
When you are done working with the array, you must call cgiStringArrayFree() with the array pointer as the argument; otherwise, you will have a memory leak.
|
cgiFormStringMultiple() returns
one of these status codes:
- cgiFormMemory:
Not enough memory is available to allocate the array to be
returned.
- cgiFormNotFound:
No occurrences were found.
- cgiFormSuccess:
At least one occurrence of the name was found.
cgiFormStringNoNewlines
The cgiFormStringNoNewlines()
function is equivalent to cgiFormString(),
except that any carriage returns or line feeds that occur in the
input are stripped out. This function is recommended for single-line
text input fields, because some browsers submit carriage returns
and line feeds when they should not. See the section "cgiFormString,"
earlier in this chapter, for further information.
Use this code:
cgiFormResultType cgiFormStringNoNewlines(char *name, char *result, int max)
cgiFormStringSpaceNeeded
The cgiFormStringSpaceNeeded()
function determines the length of the input text buffer needed
to receive the contents of the specified input field. This is
useful if the programmer wants to allocate sufficient memory for
input of arbitrary length. The actual length of the string retrieved
by a subsequent call to cgiFormString()
may be slightly shorter but will never be longer than the returned
*result parameter. Use this
code:
cgiFormResultType cgiFormStringSpaceNeeded(char *name, int *length)
Table 8.16 explains the parameters of the cgiFormStringSpaceNeeded
function.
Table 8.16. The cgiFormStringSpaceNeeded()
parameters.
| Argument | Meaning
|
| *length
| A pointer to the space allocated for the returned size of the input name.
|
| *name |
Name of the input field in the form. Usually, this is the Name attribute of the Web fill-out form input type.
|
cgiFormStringSpaceNeeded()
returns one of these status codes:
- On success, cgiFormStringSpaceNeeded()
sets the value pointed to by the parameter *length
to the number of bytes of data, including the terminating null
character, and returns cgiFormSuccess.
- If the specified field name cannot be retrieved, cgiFormStringSpaceNeeded()
sets the value pointed to by length
to 1 and returns cgiFormNotFound.
The 1 is set to ensure space for an empty string (a single null
character) if cgiFormString()
is called despite the return value.
cgiStringArrayFree
The cgiStringArrayFree()
function frees the memory associated with a string array created
by cgiFormStringMultiple().
Use this code:
void cgiStringArrayFree(char **stringArray)
| Note |
|
**stringArray must be a pointer to an array of string pointers.
|
This section lists the various numeric functions. They are arranged
in alphabetical order for easy reference.
cgiFormCheckboxMultiple
The cgiFormCheckboxMultiple()
function determines which checkboxes among a group of checkboxes
with the same name are checked. This is distinct from radio buttons
(see the section "cgiFormRadio,"
later in this chapter). Use this code:
cgiFormResultType cgiFormCheckboxMultiple(char *name, char **valuesText,
int valuesTotal, int *result, int *invalid)
Table 8.17 explains the parameters of the cgiFormCheckboxMultiple()
function.
Table 8.17. The cgiFormCheckboxMultiple()
parameters.
| Argument | Meaning
|
| invalid
| Set to the number of invalid selections that were submitted, which should be 0 unless the form and the valuesText array do not agree.
|
| *name |
Identifies the Name attribute of a group of commonly named checkbox elements.
|
| *result
| Points to an array of integers with as many elements as there are strings in the valuesText array. For each choice in the valuesText array that is selected, the corresponding integer in the result array is set
to 1; other entries in the result array are set to 0.
|
| **valuesText
| Points to an array of strings identifying the Value attribute of each checkbox.
|
| valuesTotal
| Indicates the total number of checkboxes. |
cgiFormCheckboxMultiple()
returns one of these status codes:
- cgiFormNotFound:
No valid checkboxes were checked.
- cgiFormSuccess:
At least one valid checkbox was checked.
cgiFormCheckboxSingle
The cgiFormCheckboxSingle()
function determines whether the checkbox with the specified name
is checked. cgiFormCheckboxSingle()
is intended for single checkboxes with a unique name. Use this
code:
cgiFormResultType cgiFormCheckboxSingle(char *name)
cgiFormCheckboxSingle() returns
one of these status codes:
- cgiFormNotFound:
The checkbox is not checked.
- cgiFormSuccess:
The button is checked.
cgiFormDouble
The cgiFormDouble() function
attempts to retrieve the floating-point value sent for the specified
input field. Use this code:
cgiFormResultType cgiFormDouble(char *name, double *result, double defaultV)
The value pointed to by result
is set to the value submitted.
Table 8.18 explains the parameters of the cgiFormDouble()
function.
Table 8.18. The cgiFormDouble()
parameters.
| Argument | Meaning
|
| defaultV
| When the status is empty, bad, or not found, the value stored in result is the value passed in the defaultV argument.
|
| *name |
Name of the input field in the form. Usually, this is the Name attribute of the Web fill-out form input type.
|
| *result
| A pointer to the location where the retrieved number should be stored.
|
cgiFormDouble() returns one
of these status codes:
- cgiFormBadType:
The value submitted is not a number.
- cgiFormEmpty:
The value submitted is an empty string.
- cgiFormNotFound:
No such input field was submitted.
- cgiFormSuccess:
The value was retrieved successfully.
cgiFormDoubleBounded
The cgiFormDoubleBounded()
function attempts to retrieve the number sent for the specified
input field and constrains the result to be within the specified
bounds. Use this code:
cgiFormResultType cgiFormDoubleBounded(char *name, double *result, double min,
double max, double defaultV)
Table 8.19 lists the parameters of the cgiFormDoubleBounded()
function.
Table 8.19. The cgiFormDoubleBounded()
parameters.
| Argument | Meaning
|
| defaultV
| When the status is empty, bad, or not found, the value stored in result is the value passed in the defaultV argument.
|
| max |
The maximum value to be returned in result.
|
| min |
The minimum value to be returned in result.
|
| *name |
Name of the input field in the form. Usually, this is the Name attribute of the Web fill-out form input type.
|
| *result
| A pointer to the location where the retrieved number should be stored.
|
cgiFormDoubleBounded() returns
one of these status codes:
- cgiFormBadType:
The value submitted is not an integer.
- cgiFormConstrained:
The value was out of bounds and result
was adjusted accordingly.
- cgiFormEmpty:
The value submitted is an empty string.
- cgiFormNotFound:
No such input field was submitted.
- cgiFormSuccess:
The value was retrieved successfully.
cgiFormInteger
The cgiFormInteger() function
attempts to retrieve the integer sent for the specified input
field. The value pointed to by the result is set to the value
submitted. Use this code:
cgiFormResultType cgiFormInteger(char *name, int *result, int defaultV)
Table 8.20 explains the parameters of the cgiFormInteger()
function.
Table 8.20. The cgiFormInteger()
parameters.
| Argument | Meaning
|
| defaultV
| When the status is not success, the value stored in result is the value passed in the defaultV argument.
|
| *name |
Name of the input field in the form. Usually, this is the Name attribute of the Web fill-out form input type.
|
| *result
| A pointer to the location where the retrieved integer should be stored.
|
cgiFormInteger() returns
one of these status codes:
- cgiFormBadType:
The value submitted is not an integer.
- cgiFormEmpty:
The value submitted is an empty string.
- cgiFormNotFound:
No such input field was submitted.
- cgiFormSuccess:
The value was retrieved successfully.
cgiFormIntegerBounded
The cgiFormIntegerBounded()
function attempts to retrieve the integer sent for the specified
input field and constrains the result to be within the specified
bounds. Use this code:
cgiFormResultType cgiFormIntegerBounded(char *name, int *result, int min,
int max, int defaultV)
Table 8.21 explains the parameters of the cgiFormIntegerBounded()
function.
Table 8.21. The cgiFormIntegerBounded()
parameters.
| Argument | Meaning
|
| defaultV
| When the status is empty, bad, or not found, the value stored in result is the value passed in the defaultV argument.
|
| max |
The maximum value to be returned in result.
|
| min |
The minimum value to be returned in result.
|
| *name |
Name of the input field in the form. Usually, this is the Name attribute of the Web fill-out form input type.
|
| *result
| A pointer to the location where the retrieved integer should be stored.
|
cgiFormIntegerBounded() returns
one of these status codes:
- cgiFormBadType:
The value submitted is not an integer.
- cgiFormConstrained:
The value was out of bounds and result
was adjusted accordingly.
- cgiFormEmpty:
The value submitted is an empty string.
- cgiFormNotFound:
No such input field was submitted.
- cgiFormSuccess:
The value was retrieved successfully.
cgiFormRadio
The cgiFormRadio() function
determines which, if any, of a group of radio buttons with the
same name was selected. Use this code:
cgiFormResultType cgiFormRadio(char *name, char **valuesText, int valuesTotal,
int *result, int defaultV)
Table 8.22 explains the parameters of the cgiFormRadio()
function.
Table 8.22. The cgiFormRadio()
parameters.
| Argument | Meaning
|
| defaultV
| The value of result is set to the value of default if no radio button was checked or an invalid selection was made.
|
| *name |
Identifies the Name attribute of a group of commonly named radio elements.
|
| *result
| The value pointed to by result is set to the position of the actual choice selected within the valuesText array.
|
| **valuesText
| Points to an array of strings identifying the Value attribute of each radio button.
|
| valuesTotal
| Indicates the total number of radio buttons.
|
cgiFormRadio() returns one
of these status codes:
- cgiFormNoSuchChoice:
The radio box submitted does not match any of the possibilities
in the valuesText array.
- cgiFormNotFound:
No box was checked.
- cgiFormSuccess:
A checked radio box was found in the group.
cgiFormSelectMultiple
The cgiFormSelectMultiple()
function retrieves the selection numbers associated with a Select
element that allows multiple selections. Use this code:
cgiFormResultType cgiFormSelectMultiple(char *name, char **choicesText,
int choicesTotal, int *result, int *invalid)
Table 8.23 explains the parameters of the cgiFormSelectMultiple()
function.
Table 8.23. The cgiFormSelectMultiple()
parameters.
| Argument | Meaning
|
| **choicesText
| Points to an array of strings identifying each choice.
|
| choicesTotal
| Indicates the total number of choices. |
| *invalid
| The integer pointed to by invalid is set to the number of invalid selections that were submitted, which should be 0 unless the form and the choicesText array do not agree.
|
| *name |
Identifies the Name attribute of the Select element.
|
| *result
| Points to an array of integers with as many elements as there are strings in the choicesText array. For each choice in the choicesText array that is selected, the corresponding integer in the result array is set to 1;
other entries in the result array are set to 0.
|
cgiFormSelectMultiple() returns
one of these status codes:
- cgiFormNotFound:
No valid selections were submitted.
- cgiFormSuccess:
At least one valid selection was retrieved successfully.
cgiFormSelectSingle
The function cgiFormSelectSingle()
retrieves the selection number associated with a Select
element that does not allow multiple selections. Use this code:
cgiFormResultType cgiFormSelectSingle(char *name, char **choicesText,
int choicesTotal, int *result, int defaultV)
Table 8.24 explains the parameters of the cgiFormSelectSingle()
function.
Table 8.24. The cgiFormSelectSingle()
parameters.
| Argument | Meaning
|
| **choicesText
| Points to an array of strings identifying each choice.
|
| choicesTotal
| Indicates the total number of choices. |
| defaultV
| Result is set to the value of default if no selection was submitted or an invalid selection was made.
|
| *name |
Identifies the Name attribute of the Select element.
|
| *result
| Value pointed to by result is set to the position of the actual choice selected within the choicesText array.
|
cgiFormSelectSingle() returns
one of these status codes:
- cgiFormNoSuchChoice:
The selection does not match any of the possibilities in the choicesText
array.
- cgiFormNotFound:
No selection was submitted.
- cgiFormSuccess:
The value was retrieved successfully.
Only one of the CGI Header
functions-cgiHeaderLocation(),
cgiHeaderStatus(), or cgiHeaderContentType()-should
be invoked for each CGI transaction.
You call cgiHeaderLocation()
to specify a new URI if the document request should be redirected.
You call cgiHeaderStatus()
if you want to respond to a request with an HTTP error status
code and message; see the HTTP documentation for the legal codes.
You usually call cgiHeaderContentType(),
however, to specify the MIME type of the document (such as text/html);
you then can output the actual document directly to cgiOut.
cgiHeaderContentType
The cgiHeaderContentType()
function should be called if the programmer wants to output a
new document in response to the user's request. This is the normal
case. The single argument is the MIME document type of the response;
typical values are text/html
for HTML documents, text/plain
for plain ASCII without HTML tags, image/gif
for GIF images, and audio/basic
for .au-format audio.
Use this code:
void cgiHeaderContentType(char *mimeType)
cgiHeaderLocation
The cgiHeaderLocation() function
should be called if the programmer wants to redirect the user
to a different URI. No further output is needed in this case.
Use this code:
void cgiHeaderLocation(char *redirectUrl)
cgiHeaderStatus
The cgiHeaderStatus() function
should be called if the programmer wants to output an HTTP error
status message instead of a document. The status code is the first
argument; the second argument is the status message to be displayed
to the user. Use this code:
void cgiHeaderStatus(int status, char *statusMessage)
cgiMain
The programmer must write this function, which performs the unique
task of the program and is invoked by the true main()
function, found in the cgic
library itself. The return value from cgiMain
will be the return value of the program. It is expected that the
user will make numerous calls to the cgiForm
functions from within this function. See "Writing a cgic
Application," earlier in this chapter, for details.
Use this code:
int cgiMain()
cgiSaferSystem
The cgiSaferSystem() function
is a convenience function used to invoke the system()
function less dangerously. That is, cgiSaferSystem()
escapes the shell metacharacters ; and |, which can otherwise
cause other programs to be invoked beyond the one intended by
the programmer. However, understanding the shell commands you
invoke and ensuring that you do not invoke the shell in ways that
permit the Web user to run arbitrary programs is your responsibility.
Use this code:
int cgiSaferSystem(char *command)
cgiWriteEnvironment and
cgiReadEnvironment
These two functions are designed to work together:
- The function cgiWriteEnvironment()
can be used to write the entire CGI environment, including form
data, to the specified output file. Use this code:
cgiEnvironmentResultType cgiWriteEnvironment(char
*filename)
- The function cgiReadEnvironment()
restores a CGI environment saved to the specified file by cgiWriteEnvironment().
Use this code:
cgiEnvironmentResultType cgiReadEnvironment(char
*filename)
The function cgiReadEnvironment()
can be used to restore environments saved by the cgiWriteEnvironment()
from the specified input file. Of course, these will work as expected
only if you use the cgic
copies of the CGI environment variables and cgiIn
and cgiOut rather than STDIN
and STDOUT. These functions
are useful in order to capture real CGI situations while the Web
server is running, and then to re-create them in a debugging environment.
Both functions return one of these status codes:
- cgiEnvironmentIO:
Indicates an I/O error.
- cgiEnvironmentMemoryOn:
Indicates an out-of-memory error.
- cgiEnvironmentSuccess:
Indicates success.
This section provides a reference guide to the various global
variables provided by cgic
for the programmer to use. These variables always should be used
in preference to STDIN, STDOUT,
and calls to getenv() in
order to ensure compatibility with the cgic
CGI debugging features.
Most of these variables are equivalent to various CGI environment
variables. The most important difference is that the cgic
environment string variables are never null pointers. They always
point to valid C strings of zero or more characters. Table 8.25
lists the environment string variables.
Table 8.25. cgic
global environment string variables.
| Name and Format | Meaning |
| char *cgiAccept
| Points to a space-separated list of MIME content types acceptable to the browser (see "cgiHeaderContentType") or an empty string. Unfortunately, this variable is not supplied by most current browsers. Programmers who
want to make decisions based on the capabilities of the browser should check the cgiUserAgent variable against a list of browsers and capabilities instead.
|
| char *cgiAuthType
| Points to the type of authorization used for the request, if any, or an empty string if none or unknown.
|
| char *cgiContentType
| Points to the MIME content type of the information submitted by the user, if any; points to an empty string if no information was submitted. If this string is equal to application/x-www-form-urlencoded, the cgic library
automatically examines the form data submitted. If this string has any other non-empty value, a different type of data has been submitted. This is currently very rare because most browsers can submit only forms, but if it is of interest to your
application, the submitted data can be read from the cgiIn file pointer.
|
| char *cgiGatewayInterface
| Points to the name of the gateway interface (usually CGI/1.1) or to an empty string, if unknown.
|
| char *cgiPathInfo
| Most Web servers recognize any additional path information in the URI of the request beyond the name of the CGI program itself and pass that information on to the program. cgiPathInfo points to this additional path information.
|
| char *cgiPathTranslated
| Points to additional path information translated by the server into a file system path on the local server.
|
| char *cgiQueryString
| Contains any query information submitted by the user as a result of a Get method form or an Isindex tag. Note that this information does not need to be parsed directly unless an Isindex tag was used. It
normally is parsed automatically by the cgic library. Use the cgiForm family of functions to retrieve the values associated with form input fields.
|
| char *cgiRemoteAddr
| Points to the dotted-decimal IP address of the browser, if known, or an empty string if unknown.
|
| char *cgiRemoteHost
| Points to the fully resolved host name of the browser, if known, or an empty string if unknown.
|
| char *cgiRemoteIdent
| Points to the user name volunteered by the user via the user identification protocol; points to an empty string if unknown. This information is not secure. Identification daemons can be installed by users on unsecured systems such as
Windows machines.
|
| char *cgiRemoteUser
| Points to the user name under which the user has authenticated; points to an empty string if no authentication has taken place. The certainty of this information depends on the type of authorization in use; see char
*cgi:AuthType.
|
| char *cgiRequestMethod
| Points to the method used in the request (usually Get or Post) or an empty string if unknown (this should not happen).
|
| char *cgiScriptName
| Points to the name under which the program was invoked.
|
| char *cgiServerName
| Points to the name of the server or to an empty string if unknown.
|
| char *cgiServerPort
| Points to the port number on which the server is listening for HTTP connections (usually 80) or an empty string if unknown.
|
| char *cgiServerProtocol
| Points to the protocol in use (usually HTTP/1.0) or to an empty string if unknown.
|
| char *cgiServerSoftware
| Points to the name of the server software or to an empty string if unknown.
|
| char *cgiUserAgent
| Points to the name of the browser in use or an empty string if this information is not available.
|
| FILE *cgiIn
| Points to CGI input. In 99 percent of cases, you will not need this. However, in future applications, documents other than form data are posted to the server, in which case this file pointer may be read from in order to retrieve the
contents.
|
| FILE *cgiOut
| Points to CGI output. The CGI Header functions, such as cgiHeaderContentType, should be used first to output the MIME headers. The output HTML page, GIF image, or other Web document then should be written to
cgiOut by the programmer using standard C I/O functions such as fprintf() and fwrite(). cgiOut normally is equivalent to STDOUT. However, it is recommended that cgiOut be used to ensure compatibility
with future versions of cgic for specialized environments.
|
| int cgiContentLength
| The number of bytes of form or query data received. Note that if the submission is a form or query submission, the library reads and parses all the information directly from cgiIn and/or cgiQueryString. The programmer
should not do so and, indeed, the cgiIn pointer will be at end-of-file in such cases.
|
In this chapter, you learned about three very useful existing
libraries on the Net: cgi-lib.pl,
CGI.pm, and cgic.
You should be able to put these libraries to regular use, saving
yourself countless hours of time reinventing existing applications.
I hope that you have the opportunity to return to this chapter
many times in the future for use as a valuable reference tool.
Listing 8.7. Using self-referencing URLs to jump to internal
links.
01: #!/usr/local/bin/perl
02:
03: use CGI;
04: $query = new CGI;
05:
06: # We generate a regular HTML file containing a very long list
07: # and a pop-up menu that does nothing except to show that we
08: # don't lose the state information.
09: print $query->header;
10: print $query->start_html("Internal Links Example");
11: print "<H1>Internal Links Example</H1>\n";
12:
13: print "<A NAME=\"start\"></A>\n"; # an anchor point at the top
14:
15: # pick a default starting value;
16: $query->param('amenu','FOO1') unless $query->param('amenu');
17:
18: print $query->startform;
19: print $query->popup_menu('amenu',[('FOO1'..'FOO9')]);
20: print $query->submit,$query->endform;
21:
22: # We create a long boring list for the purposes of illustration.
23: $myself = $query->self_url;
24: print "<OL>\n";
25: for (1..100) {
26: print qq{<LI>List item #$_<A HREF="$myself#start">Jump to top</A>\n};
27: }
28: print "</OL>\n";
Listing 8.8. Saving state information to a file.
01: use CGI;
02: $query = new CGI;
03:
04: print $query->header;
05: print $query->start_html("Save and Restore Example");
06: print "<;H1>Save and Restore Example<;/H1>\n";
07:
08: # Here's where we take action on the previous request
09: &save_parameters($query) if $query->param('action') eq 'save';
10: $query = &restore_parameters($query) if $query->param('action') eq
'restore';
11:
12: # Here's where we create the form
13: print $query->startform;
14: print "Popup 1: ",$query->popup_menu('popup1',
['eenie','meenie','minie']),"\n";
15: print "Popup 2: ",$query->popup_menu('popup2',['et','lux','perpetua']),"\n";
16: print "<;P>";
17: print "Save/restore state from file: ",$query->textfield('savefile',
'state.sav'),"\n";
18: print "<;P>";
19: print $query->submit('action','save'),$query->submit('action','restore');
20: print $query->submit('action','usual query');
21: print $query->endform;
22:
23: # Here we print out a bit at the end
24: print $query->end_html;
25:
26: sub save_parameters {
27: local($query) = @_;
28: local($filename) = &clean_name($query->param('savefile'));
29: if (open(FILE,">$filename")) {
30: $query->save(FILE);
31: close FILE;
32: print "<;STRONG>State has been saved to file $filename<;/STRONG>\n";
33: } else {
34: print "<;STRONG>Error:<;/STRONG>
couldn't write to file $filename: $!\n";
35: }
36: }
37:
38: sub restore_parameters {
39: local($query) = @_;
40: local($filename) = &clean_name($query->param('savefile'));
41: if (open(FILE,$filename)) {
42: $query = new CGI(FILE);
# Throw out the old query, replace it with a new one
43: close FILE;
44: print "<;STRONG>State has been restored from file
$filename<;/STRONG>\n";
45: } else {
46: print "<;STRONG>Error:<;/STRONG>
couldn't restore file $filename: $!\n";
47: }
48: return $query;
49: }
50:
51:
52: # Very important subroutine - get rid of all the naughty
53: # metacharacters from the file name. If there are, we
54: # complain bitterly and die.
55: sub clean_name {
56: local($name) = @_;
57: unless ($name=~/^[\w\.-]+$/) {
58: print "<;STRONG>$name has naughty characters. Only ";
59: print "alphanumerics are allowed. You can't use absolute
names.<;/STRONG>";
60: die "Attempt to use naughty characters";
61: }
62: return $name;
63: }
| Q | Are there other libraries?
|
| A | Yes, of course. One set of libraries still is being developed, but it should be ready by the time you read this guide. The libraries are Perl 5 modules called CGI::*. The current development set
of modules are Base.pm, Request.pm, Form.pm, URL.pm, and MiniSrv.pm. You can learn more about these modules at
http://www-genome.wi.mit.edu/WWW/tools/scripting/CGIperl
|
| Q | I can't maintain the state of my form because I have internal links that cause the state of my form to be reset. What should I do?
|
| A | A partial solution is to use the self_url() method to generate a link that preserves state information. Try the script shown in Listing 8.7, which is distributed with the CGI.pm
library.
|
| Q | How do I save data to a form using the CGI.pm library and use it later?
|
| A | This script is part of the CGI.pm distribution, and it is included here in Listing 8.8. It saves its state to a file of the user's choosing after the Save button is clicked and restores its
state after the Restore button is clicked. Notice that it's very important to check the filename for shell metacharacters so that the script doesn't inadvertently open up a command or overwrite someone's file. In order for this to work, the script's
current directory must be writable by
"nobody".#!/usr/local/bin/perl
|

|