Current Perl documentation can be found at perldoc.perl.org.
Here is our local, out-dated (pre-5.6) version:
print $query->filefield(-name=>'uploaded_file', -default=>'starting value', -size=>50, -maxlength=>80); -or-
print $query->filefield('uploaded_file','starting value',50,80);
filefield()
will return a
file upload field for Netscape 2.0 browsers. In order to take full
advantage of this you must use the new
multipart encoding scheme for the form. You can do this either by calling startform() with an encoding type of $CGI::MULTIPART, or by calling the new method start_multipart_form() instead of vanilla startform().
The first parameter is the required name for the field (-name).
The beta2 version of Netscape 2.0 currently doesn't pay any attention to this field, and so the starting value will always be blank. Worse, the field loses its ``sticky'' behavior and forgets its previous contents. The starting value field is called for in the HTML specification, however, and possibly later versions of Netscape will honor it.
When the form is processed, you can retrieve the entered filename by calling
param().
$filename = $query->param('uploaded_file');
In Netscape Navigator 2.0, the filename that gets returned is the full local filename on the remote user's machine. If the remote user is on a Unix machine, the filename will follow Unix conventions:
/path/to/the/file
On an MS-DOS/Windows and OS/2 machines, the filename will follow DOS conventions:
C:\PATH\TO\THE\FILE.MSW
On a Macintosh machine, the filename will follow Mac conventions:
HD 40:Desktop Folder:Sort Through:Reminders
The filename returned is also a file handle. You can read the contents of the file using standard Perl file reading calls:
# Read a text file and print it out while (<$filename>) { print; }
# Copy a binary file to somewhere safe open (OUTFILE,">>/usr/local/web/users/feedback"); while ($bytesread=read($filename,$buffer,1024)) { print OUTFILE $buffer; }
When a file is uploaded the browser usually sends along some information along with it in the format of headers. The information usually includes the
MIME content type. Future browsers may send other information as well (such as modification date and size). To retrieve this information, call
uploadInfo().
It returns a reference to an associative array containing all the document headers.
$filename = $query->param('uploaded_file'); $type = $query->uploadInfo($filename)->{'Content-Type'}; unless ($type eq 'text/html') { die "HTML FILES ONLY!"; }
If you are using a machine that recognizes ``text'' and ``binary'' data modes, be sure to understand when and how to use them (see the Camel book). Otherwise you may find that binary files are corrupted during file uploads.
JAVASCRIPTING: The -onChange, -onFocus, -onBlur,
-onMouseOver, -onMouseOut and -onSelect parameters are recognized. See
textfield()
for details.
print $query->popup_menu('menu_name', ['eenie','meenie','minie'], 'meenie');
-or-
%labels = ('eenie'=>'your first choice', 'meenie'=>'your second choice', 'minie'=>'your third choice'); print $query->popup_menu('menu_name', ['eenie','meenie','minie'], 'meenie',\%labels);
-or (named parameter style)-
print $query->popup_menu(-name=>'menu_name', -values=>['eenie','meenie','minie'], -default=>'meenie', -labels=>\%labels);
popup_menu()
creates a
menu.
The required first argument is the menu's name (-name).
When the form is processed, the selected value of the popup menu can be retrieved using:
$popup_menu_value = $query->param('menu_name');
JAVASCRIPTING:
popup_menu()
recognizes the following event handlers:
-onChange, -onFocus, -onMouseOver, -onMouseOut, and
-onBlur. See the
textfield()
section for
details on when these handlers are called.
print $query->scrolling_list('list_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],5,'true'); -or-
print $query->scrolling_list('list_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],5,'true', \%labels);
-or-
print $query->scrolling_list(-name=>'list_name', -values=>['eenie','meenie','minie','moe'], -default=>['eenie','moe'], -size=>5, -multiple=>'true', -labels=>\%labels);
scrolling_list()
creates a scrolling list.
The first and second arguments are the list name (-name) and values (-values). As in the popup menu, the second argument should be an array reference.
When this form is processed, all selected list items will be returned as a list under the parameter name 'list_name'. The values of the selected items can be retrieved with:
@selected = $query->param('list_name');
JAVASCRIPTING:
scrolling_list()
recognizes the following event handlers:
-onChange, -onFocus, -onMouseOver, -onMouseOut
and -onBlur. See
textfield()
for the
description of when these handlers are called.
print $query->checkbox_group(-name=>'group_name', -values=>['eenie','meenie','minie','moe'], -default=>['eenie','moe'], -linebreak=>'true', -labels=>\%labels);
print $query->checkbox_group('group_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],'true',\%labels);
HTML3-COMPATIBLE BROWSERS ONLY:
print $query->checkbox_group(-name=>'group_name', -values=>['eenie','meenie','minie','moe'], -rows=2,-columns=>2);
checkbox_group()
creates a list of checkboxes that are related by the same name.
The first and second arguments are the checkbox name and values, respectively (-name and -values). As in the popup menu, the second argument should be an array reference. These values are 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.
checkbox_group()
to return an
HTML3 compatible table containing the checkbox group formatted with the specified number of rows and columns. You can provide just the -columns parameter if you wish; checkbox_group will calculate the correct number of rows for you.
To include row and column headings in the returned table, you can use the -rowheaders and -colheaders parameters. Both of these accept a pointer to an array of headings to use. The headings are just decorative. They don't reorganize the interpretation of the checkboxes -- they're still a single named unit.
When the form is processed, all checked boxes will be returned as a list under the parameter name 'group_name'. The values of the ``on'' checkboxes can be retrieved with:
@turned_on = $query->param('group_name');
The value returned by
checkbox_group()
is
actually an array of button elements. You can capture them and use them
within tables, lists, or in other creative ways:
@h = $query->checkbox_group(-name=>'group_name',-values=>\@values); &use_in_creative_way(@h);
JAVASCRIPTING:
checkbox_group()
recognizes the
-onClick
parameter. This specifies a JavaScript code fragment or function call to be
executed every time the user clicks on any of the buttons in the group. You
can retrieve the identity of the particular button clicked on using the
``this'' variable.
print $query->checkbox(-name=>'checkbox_name', -checked=>'checked', -value=>'ON', -label=>'CLICK ME');
-or-
print $query->checkbox('checkbox_name','checked','ON','CLICK ME');
checkbox()
is used to
create an isolated checkbox that isn't logically related to any others.
The first parameter is the required name for the checkbox (-name). It will also be used for the user-readable label printed next to the checkbox.
The value of the checkbox can be retrieved using:
$turned_on = $query->param('checkbox_name');
JAVASCRIPTING:
checkbox()
recognizes the
-onClick
parameter. See
checkbox_group()
for
further details.
print $query->radio_group(-name=>'group_name', -values=>['eenie','meenie','minie'], -default=>'meenie', -linebreak=>'true', -labels=>\%labels);
-or-
print $query->radio_group('group_name',['eenie','meenie','minie'], 'meenie','true',\%labels);
HTML3-COMPATIBLE BROWSERS ONLY:
print $query->radio_group(-name=>'group_name', -values=>['eenie','meenie','minie','moe'], -rows=2,-columns=>2);
radio_group()
creates a
set of logically-related radio buttons (turning one member of the group on
turns the others off)
The first argument is the name of the group and is required (-name).
radio_group()
to return an
HTML3 compatible table containing the radio group formatted with the specified number of rows and columns. You can provide just the -columns parameter if you wish; radio_group will calculate the correct number of rows for you.
To include row and column headings in the returned table, you can use the -rowheader and -colheader parameters. Both of these accept a pointer to an array of headings to use. The headings are just decorative. They don't reorganize the interpetation of the radio buttons -- they're still a single named unit.
When the form is processed, the selected radio button can be retrieved using:
$which_radio_button = $query->param('group_name');
The value returned by
radio_group()
is
actually an array of button elements. You can capture them and use them
within tables, lists, or in other creative ways:
@h = $query->radio_group(-name=>'group_name',-values=>\@values); &use_in_creative_way(@h);
print $query->submit(-name=>'button_name', -value=>'value');
-or-
print $query->submit('button_name','value');
submit()
will create the
query submission button. Every form should have one of these.
The first argument (-name) is optional. You can give the button a name if you have several submission buttons in your form and you want to distinguish between them. The name will also be used as the user-visible label. Be aware that a few older browsers don't deal with this correctly and never send back a value from a button.
You can figure out which button was pressed by using different values for each one:
$which_one = $query->param('button_name');
JAVASCRIPTING:
radio_group()
recognizes the
-onClick
parameter. See
checkbox_group()
for
further details.
print $query->reset
reset()
creates the ``reset'' button. Note that it restores the form to its value from the last time the script was called,
NOT necessarily to the defaults.
print $query->defaults('button_label')
defaults()
creates a button
that, when invoked, will cause the form to be completely reset to its
defaults, wiping out all the changes the user ever made.
print $query->hidden(-name=>'hidden_name', -default=>['value1','value2'...]);
-or-
print $query->hidden('hidden_name','value1','value2'...);
hidden()
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 first argument is required and specifies the name of this field (-name).
Fetch the value of a hidden field this way:
$hidden_value = $query->param('hidden_name');
Note, that just like all the other form elements, the value of a hidden field is ``sticky''. If you want to replace a hidden field with some other values after the script has been called once you'll have to do it manually:
$query->param('hidden_name','new','values','here');
print $query->image_button(-name=>'button_name', -src=>'/source/URL', -align=>'MIDDLE');
-or-
print $query->image_button('button_name','/source/URL','MIDDLE');
image_button()
produces
a clickable image. When it's clicked on the position of the click is
returned to your script as ``button_name.x'' and ``button_name.y'', where
``button_name'' is the name you've assigned to it.
JAVASCRIPTING:
image_button()
recognizes the
-onClick
parameter. See
checkbox_group()
for
further details.
The first argument (-name) is required and specifies the name of this field.
Fetch the value of the button this way: $x
=
$query->param('button_name.x'); $y =
$query->param('button_name.y');
print $query->button(-name=>'button_name', -value=>'user visible label', -onClick=>"do_something()");
-or-
print $query->button('button_name',"do_something()");
button()
produces a button
that is compatible with Netscape 2.0's JavaScript. When it's pressed the
fragment of JavaScript code pointed to by the -onClick parameter will be executed. On non-Netscape browsers this form element will
probably not even display.
Netscape browsers versions 1.1 and higher support a so-called ``cookie'' designed to help maintain state within a browser session. CGI.pm has several methods that support cookies.
A cookie is a name=value pair much like the named parameters in a CGI query string. CGI scripts create one or more cookies and send them to the browser in the HTTP header. The browser maintains a list of cookies that belong to a particular Web server, and returns them to the CGI script during subsequent interactions.
In addition to the required name=value pair, each cookie has several optional attributes:
This is a time/date string (in a special GMT format) that indicates when a cookie expires. The cookie will be saved and returned to your script until this expiration date is reached if the user exits Netscape and restarts it. If an expiration date isn't specified, the cookie will remain active until the user quits Netscape.
The interface to Netscape cookies is the cookie() method:
$cookie = $query->cookie(-name=>'sessionID', -value=>'xyzzy', -expires=>'+1h', -path=>'/cgi-bin/database', -domain=>'.capricorn.org', -secure=>1); print $query->header(-cookie=>$cookie);
cookie() creates a new cookie. Its parameters include:
$cookie=$query->cookie(-name=>'family information', -value=>\%childrens_ages);
"+1h" one hour from now
The cookie created by
cookie()
must be incorporated into the
HTTP header within the string returned by the
header()
method:
print $query->header(-cookie=>$my_cookie);
To create multiple cookies, give
header()
an array reference:
$cookie1 = $query->cookie(-name=>'riddle_name', -value=>"The Sphynx's Question"); $cookie2 = $query->cookie(-name=>'answers', -value=>\%answers); print $query->header(-cookie=>[$cookie1,$cookie2]);
To retrieve a cookie, request it by name by calling
cookie()
method without the -value parameter:
use CGI; $query = new CGI; %answers = $query->cookie(-name=>'answers'); # $query->cookie('answers') will work too!
The cookie and
CGI namespaces are separate. If you have a parameter named 'answers' and a cookie named 'answers', the values retrieved by
param()
and
cookie()
are independent of each other. However, it's simple to turn a
CGI parameter into a cookie, and vice-versa:
# turn a CGI parameter into a cookie $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]); # vice-versa $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);
See the cookie.cgi example script for some ideas on how to use cookies effectively.
NOTE: There appear to be some (undocumented) restrictions on Netscape cookies. In Netscape 2.01, at least, I haven't been able to set more than three cookies at a time. There may also be limits on the length of cookies. If you need to store a lot of information, it's probably better to create a unique session ID, store it in a cookie, and use the session ID to locate an external file/database saved on the server's side of the connection.
It's possible for CGI.pm scripts to write into several browser panels and windows using Netscape's frame mechanism. There are three techniques for defining new frames programmatically:
After writing out the
HTTP header, instead of creating a standard
HTML document using the
start_html()
call, create a
<FRAMESET> document that defines the frames on the page. Specify your
script(s)
(with appropriate parameters) as the
SRC for each of the frames.
There is no specific support for creating <FRAMESET> sections in CGI.pm, but the HTML is very simple to write. See the frame documentation in Netscape's home pages for details
frames
You may provide a -target parameter to the
header()
method: print
$q->header(-target=>'ResultsWindow');
This will tell Netscape to load the output of your script into the frame named ``ResultsWindow''. If a frame of that name doesn't already exist, Netscape will pop up a new window and load your script's document into that. There are a number of magic names that you can use for targets. See the frame documents on Netscape's home pages for details.
print $q->startform(-target=>'ResultsWindow');
When your script is reinvoked by the form, its output will be loaded into the frame named ``ResultsWindow''. If one doesn't already exist a new window will be created.
The script ``frameset.cgi'' in the examples directory shows one way to create pages in which the fill-out form and the response live in side-by-side frames.
CGI.pm has limited support for HTML3's cascading style sheets (css). To incorporate a stylesheet into your document, pass the
start_html()
method a
-style parameter. The value of this parameter may be a scalar, in which case it is
incorporated directly into a <
STYLE> section, or it may be a hash reference. In
the latter case you should provide the hash with one or more of -src or
-code. -src points to a
URL where an externally-defined stylesheet can be
found. -code points to a scalar value to be incorporated into a <
STYLE> section. Style definitions in -code
override similarly-named ones in -src, hence the name ``cascading.''
You may also specify the type of the stylesheet by adding the optional -type parameter to the hash pointed to by -style. If not specified, the style defaults to 'text/css'.
To refer to a style within the body of your document, add the -class parameter to any HTML element:
print h1({-class=>'Fancy'},'Welcome to the Party');
Or define styles on the fly with the -style parameter:
print h1({-style=>'Color: red;'},'Welcome to Hell');
You may also use the new span() element to apply a style to a section of text:
print span({-style=>'Color: red;'}, h1('Welcome to Hell'), "Where did that handbasket get to?" );
Note that you must import the ``:html3'' definitions to have the span() method available. Here's a quick and dirty example of using CSS's. See the CSS specification at http://www.w3.org/pub/WWW/TR/Wd-css-1.html for more information.
use CGI qw/:standard :html3/;
#here's a stylesheet incorporated directly into the page $newStyle=<<END; <!-- P.Tip { margin-right: 50pt; margin-left: 50pt; color: red; } P.Alert { font-size: 30pt; font-family: sans-serif; color: red; } --> END print header(); print start_html( -title=>'CGI with Style', -style=>{-src=>'http://www.capricorn.com/style/st1.css', -code=>$newStyle} ); print h1('CGI with Style'), p({-class=>'Tip'}, "Better read the cascading style sheet spec before playing with this!"), span({-style=>'color: magenta'}, "Look Mom, no hands!", p(), "Whooo wee!" ); print end_html;
If you are running the script from the command line or in the perl debugger, you can pass the script a list of keywords or parameter=value pairs on the command line or from standard input (you don't have to worry about tricking your script into reading from environment variables). You can pass keywords like this:
your_script.pl keyword1 keyword2 keyword3
or this:
your_script.pl keyword1+keyword2+keyword3
or this:
your_script.pl name1=value1 name2=value2
or this:
your_script.pl name1=value1&name2=value2
or even as newline-delimited parameters on standard input.
When debugging, you can use quotes and backslashes to escape characters in the familiar shell manner, letting you place spaces and other funny characters in your parameter=value pairs:
your_script.pl "name1='I am a long value'" "name2=two\ words"
The
dump()
method produces a string
consisting of all the query's name/value pairs formatted nicely as a nested
list. This is useful for debugging purposes:
print $query->dump
Produces something that looks like:
<UL> <LI>name1 <UL> <LI>value1 <LI>value2 </UL> <LI>name2 <UL> <LI>value1 </UL> </UL>
You can pass a value of 'true' to
dump()
in order to get it to print the results out as plain text, suitable for incorporating into a
<PRE> section.
As a shortcut, as of version 1.56 you can interpolate the entire CGI object into a string and it will be replaced with the a nice HTML dump shown above:
$query=new CGI; print "<H2>Current Values</H2> $query\n";
Some of the more useful environment variables can be fetched through this interface. The methods are as follows:
cookie()
for ways of setting and retrieving cooked cookies.
Called with no parameters,
raw_cookie()
returns the
packed cookie structure. You can separate it into individual cookies by
splitting on the character sequence ``; ''. Called with the name of a
cookie, retrieves the unescaped form of the cookie. You can use the regular
cookie()
method to get the names, or use the
raw_fetch()
method from the CGI::Cookie module.
NOTE: The Microsoft Internet Information Server is broken with respect to additional path information. If you use the Perl DLL library, the IIS server will attempt to execute the additional path information as a Perl script. If you use the ordinary file associations mapping, the path information will be present in the environment, but incorrect. The best thing to do is to avoid using additional path information in CGI scripts destined for use with IIS.
path_info()
but returns
the additional path information translated into a physical path, e.g.
``/usr/local/etc/httpd/htdocs/additional/stuff''.
The Microsoft IIS is broken with respect to the translated path as well.
NPH, or ``no-parsed-header'', scripts bypass the server completely by sending the complete HTTP header directly to the browser. This has slight performance benefits, but is of most use for taking advantage of HTTP extensions that are not directly supported by your server, such as server push and PICS headers.
Servers use a variety of conventions for designating CGI scripts as NPH. Many Unix servers look at the beginning of the script's name for the prefix ``nph-''. The Macintosh WebSTAR server and Microsoft's Internet Information Server, in contrast, try to decide whether a program is an NPH script by examining the first line of script output.
CGI.pm supports
NPH scripts with a special
NPH mode. When in this mode, CGI.pm will output the necessary extra header information when the
header()
and
redirect()
methods are called.
The Microsoft Internet Information Server requires NPH mode. As of version 2.30, CGI.pm will automatically detect when the script is running under IIS and put itself into this mode. You do not need to do this manually, although it won't hurt anything if you do.
There are a number of ways to put CGI.pm into NPH mode:
use CGI qw(:standard -nph)
CGI->nph(1)
print $q->header(-nph=>1);
CGI.pm provides three simple functions for producing multipart documents of the type needed to implement server push. These functions were graciously provided by Ed Jordan <ed@fidalgo.net> To import these into your namespace, you must import the ``:push'' set. You are also advised to put the script into NPH mode and to set $| to 1 to avoid buffering problems.
Here is a simple script that demonstrates server push:
#!/usr/local/bin/perl use CGI qw/:push -nph/; $| = 1; print multipart_init(-boundary=>'----------------here we go!'); while (1) { print multipart_start(-type=>'text/plain'), "The current time is ",scalar(localtime),"\n", multipart_end; sleep 1; }
This script initializes server push by calling multipart_init(). It then enters an infinite loop in which it begins a new multipart section by calling multipart_start(), prints the current local time, and ends a multipart section with multipart_end(). It then sleeps a second, and begins again.
multipart_start(-type=>$type)
Start a new part of the multipart document using the specified MIME type. If not specified, text/html is assumed.
multipart_end()
End a part. You must remember to call
multipart_end()
once for each
multipart_start().
Users interested in server push applications should also have a look at the CGI::Push module.
A potential problem with CGI.pm is that, by default, it attempts to process form POSTings no matter how large they are. A wily hacker could attack your site by sending a CGI script a huge POST of many megabytes. CGI.pm will attempt to read the entire POST into a variable, growing hugely in size until it runs out of memory. While the script attempts to allocate the memory the system may slow down dramatically. This is a form of denial of service attack.
Another possible attack is for the remote user to force CGI.pm to accept a huge file upload. CGI.pm will accept the upload and store it in a temporary directory even if your script doesn't expect to receive an uploaded file. CGI.pm will delete the file automatically when it terminates, but in the meantime the remote user may have filled up the server's disk space, causing problems for other programs.
The best way to avoid denial of service attacks is to limit the amount of memory, CPU time and disk space that CGI scripts can use. Some Web servers come with built-in facilities to accomplish this. In other cases, you can use the shell limit or ulimit commands to put ceilings on CGI resource usage.
CGI.pm also has some simple built-in protections against denial of service attacks, but you must activate them before you can use them. These take the form of two global variables in the CGI name space:
You can use these variables in either of two ways.
Set the variable at the top of the script, right after the ``use'' statement:
use CGI qw/:standard/; use CGI::Carp 'fatalsToBrowser'; $CGI::POST_MAX=1024 * 100; # max 100K posts $CGI::DISABLE_UPLOADS = 1; # no uploads
Open up CGI.pm, find the definitions for $POST_MAX
and
$DISABLE_UPLOADS, and set them to the desired values. You'll find them towards the top of the file in a subroutine named
initialize_globals().
Since an attempt to send a
POST larger than $POST_MAX
bytes will
cause a fatal error, you might want to use CGI::Carp to echo the fatal
error message to the browser window as shown in the example above.
Otherwise the remote user will see only a generic ``Internal Server'' error
message. See the CGI::Carp manual page for more details.
To make it easier to port existing programs that use cgi-lib.pl the compatibility routine ``ReadParse'' is provided. Porting is simple:
OLD VERSION require ``cgi-lib.pl''; &ReadParse; print ``The value of the antique is $in{antique}.\n'';
NEW VERSION use CGI; CGI::ReadParse print ``The value of the antique is $in{antique}.\n'';
CGI.pm's
ReadParse()
routine
creates a tied variable named %in, which can be accessed to obtain the
query variables. Like ReadParse, you can also provide your own variable.
Infrequently used features of ReadParse, such as the creation of
@in
and $in
variables, are not supported.
Once you use ReadParse, you can retrieve the query object itself this way:
$q = $in{CGI}; print $q->textfield(-name=>'wow', -value=>'does this really work?');
This allows you to start using the more interesting features of CGI.pm without rewriting your old scripts from scratch.
Copyright 1995-1997, Lincoln D. Stein. All rights reserved. It may be used and modified freely, but I do request that this copyright notice remain attached to the file. You may modify this module as you wish, but if you redistribute a modified version, please attach a note listing the modifications you have made.
Address bug reports and comments to: lstein@genome.wi.mit.edu
Thanks very much to:
#!/usr/local/bin/perl use CGI; $query = new CGI;
print $query->header; print $query->start_html("Example CGI.pm Form"); print "<H1> Example CGI.pm Form</H1>\n"; &print_prompt($query); &do_work($query); &print_tail; print $query->end_html; sub print_prompt { my($query) = @_; print $query->startform; print "<EM>What's your name?</EM><BR>"; print $query->textfield('name'); print $query->checkbox('Not my real name'); print "<P><EM>Where can you find English Sparrows?</EM><BR>"; print $query->checkbox_group( -name=>'Sparrow locations', -values=>[England,France,Spain,Asia,Hoboken], -linebreak=>'yes', -defaults=>[England,Asia]); print "<P><EM>How far can they fly?</EM><BR>", $query->radio_group( -name=>'how far', -values=>['10 ft','1 mile','10 miles','real far'], -default=>'1 mile'); print "<P><EM>What's your favorite color?</EM> "; print $query->popup_menu(-name=>'Color', -values=>['black','brown','red','yellow'], -default=>'red'); print $query->hidden('Reference','Monty Python and the Holy Grail'); print "<P><EM>What have you got there?</EM><BR>"; print $query->scrolling_list( -name=>'possessions', -values=>['A Coconut','A Grail','An Icon', 'A Sword','A Ticket'], -size=>5, -multiple=>'true'); print "<P><EM>Any parting comments?</EM><BR>"; print $query->textarea(-name=>'Comments', -rows=>10, -columns=>50); print "<P>",$query->reset; print $query->submit('Action','Shout'); print $query->submit('Action','Scream'); print $query->endform; print "<HR>\n"; } sub do_work { my($query) = @_; my(@values,$key);
print "<H2>Here are the current settings in this form</H2>";
foreach $key ($query->param) { print "<STRONG>$key</STRONG> -> "; @values = $query->param($key); print join(", ",@values),"<BR>\n"; } } sub print_tail { print <<END; <HR> <ADDRESS>Lincoln D. Stein</ADDRESS><BR> <A HREF="/">Home Page</A> END }
This module has grown large and monolithic. Furthermore it's doing many things, such as handling URLs, parsing CGI input, writing HTML, etc., that are also done in the LWP modules. It should be discarded in favor of the CGI::* modules, but somehow I continue to work on it.
Note that the code is truly contorted in order to avoid spurious warnings when programs are run with the -w switch.
CGI::Carp, URI, CGI::Request, CGI::MiniSvr, CGI::Base, CGI::Form, CGI::Apache, CGI::Switch, CGI::Push, CGI::Fast
If rather than formatting bugs, you encounter substantive content errors in these documents, such as mistakes in the explanations or code, please use the perlbug utility included with the Perl distribution.