perlman
root
<H2><A NAME="CREATING_A_FILE_UPLOAD_FIELD">CREATING A FILE UPLOAD FIELD</A></H2>
<P>
<PRE> print $query->filefield(-name=>'uploaded_file',
-default=>'starting value',
-size=>50,
-maxlength=>80);
-or-
</PRE>
<P>
<PRE> print $query->filefield('uploaded_file','starting value',50,80);
</PRE>
<P>
<CODE>filefield()</CODE> will return a
file upload field for Netscape 2.0 browsers. In order to take full
advantage of this <EM>you must use the new
multipart encoding scheme</EM> for the form. You can do this either by calling <STRONG>startform()</STRONG> with an encoding type of <STRONG>$CGI::MULTIPART</STRONG>, or by calling the new method <STRONG>start_multipart_form()</STRONG> instead of vanilla <STRONG>startform()</STRONG>.
<DL>
<DT><STRONG>Parameters</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
The first parameter is the required name for the field (-name).
<P><LI><STRONG>.</STRONG>
The optional second parameter is the starting value for the field contents
to be used as the default file name (-default).
<P>
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
<FONT SIZE=-1>HTML</FONT> specification, however, and possibly later versions of Netscape will honor it.
<P><LI><STRONG>.</STRONG>
The optional third parameter is the size of the field in characters
(-size).
<P><LI><STRONG>.</STRONG>
The optional fourth parameter is the maximum number of characters the field
will accept (-maxlength).
</DL>
<P>
When the form is processed, you can retrieve the entered filename by calling
<CODE>param().</CODE>
<P>
<PRE> $filename = $query->param('uploaded_file');
</PRE>
<P>
In Netscape Navigator 2.0, the filename that gets returned is the full
local filename on the <STRONG>remote user's</STRONG> machine. If the remote user is on a Unix machine, the filename will follow
Unix conventions:
<P>
<PRE> /path/to/the/file
</PRE>
<P>
On an MS-DOS/Windows and
<FONT SIZE=-1>OS/2</FONT> machines, the filename will follow
<FONT SIZE=-1>DOS</FONT> conventions:
<P>
<PRE> C:\PATH\TO\THE\FILE.MSW
</PRE>
<P>
On a Macintosh machine, the filename will follow Mac conventions:
<P>
<PRE> HD 40:Desktop Folder:Sort Through:Reminders
</PRE>
<P>
The filename returned is also a file handle. You can read the contents of
the file using standard Perl file reading calls:
<P>
<PRE> # Read a text file and print it out
while (<$filename>) {
print;
}
</PRE>
<P>
<PRE> # Copy a binary file to somewhere safe
open (OUTFILE,">>/usr/local/web/users/feedback");
while ($bytesread=read($filename,$buffer,1024)) {
print OUTFILE $buffer;
}
</PRE>
<P>
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
<FONT SIZE=-1>MIME</FONT> content type. Future browsers may send other information as well (such as modification date and size). To retrieve this information, call
<CODE>uploadInfo().</CODE> It returns a reference to an associative array containing all the document headers.
<P>
<PRE> $filename = $query->param('uploaded_file');
$type = $query->uploadInfo($filename)->{'Content-Type'};
unless ($type eq 'text/html') {
die "HTML FILES ONLY!";
}
</PRE>
<P>
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.
<P>
<FONT SIZE=-1>JAVASCRIPTING:</FONT> The <STRONG>-onChange</STRONG>, <STRONG>-onFocus</STRONG>, <STRONG>-onBlur</STRONG>,
<STRONG>-onMouseOver</STRONG>, <STRONG>-onMouseOut</STRONG> and <STRONG>-onSelect</STRONG> parameters are recognized. See
<CODE>textfield()</CODE> for details.
<H2><A NAME="CREATING_A_POPUP_MENU">CREATING A POPUP MENU</A></H2>
<P>
<PRE> print $query->popup_menu('menu_name',
['eenie','meenie','minie'],
'meenie');
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> %labels = ('eenie'=>'your first choice',
'meenie'=>'your second choice',
'minie'=>'your third choice');
print $query->popup_menu('menu_name',
['eenie','meenie','minie'],
'meenie',\%labels);
</PRE>
<P>
<PRE> -or (named parameter style)-
</PRE>
<P>
<PRE> print $query->popup_menu(-name=>'menu_name',
-values=>['eenie','meenie','minie'],
-default=>'meenie',
-labels=>\%labels);
</PRE>
<P>
<CODE>popup_menu()</CODE> creates a
menu.
<OL>
<LI><STRONG>.</STRONG>
<P>
The required first argument is the menu's name (-name).
<P><LI><STRONG>.</STRONG>
The required second argument (-values) is an array <STRONG>reference</STRONG>
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''.
<P><LI><STRONG>.</STRONG>
The optional third parameter (-default) is the name of the default menu
choice. If not specified, the first item will be the default. The values of
the previous choice will be maintained across queries.
<P><LI><STRONG>.</STRONG>
The optional fourth parameter (-labels) is provided for people who want to
use different values for the user-visible label inside the popup menu nd
the value returned to your script. It's a pointer to an associative array
relating menu values to user-visible labels. If you leave this parameter
blank, the menu values will be displayed by default. (You can also leave a
label undefined if you want to).
</OL>
<P>
When the form is processed, the selected value of the popup menu can be
retrieved using:
<P>
<PRE> $popup_menu_value = $query->param('menu_name');
</PRE>
<P>
<FONT SIZE=-1>JAVASCRIPTING:</FONT>
<CODE>popup_menu()</CODE> recognizes the following event handlers:
<STRONG>-onChange</STRONG>, <STRONG>-onFocus</STRONG>, <STRONG>-onMouseOver</STRONG>, <STRONG>-onMouseOut</STRONG>, and
<STRONG>-onBlur</STRONG>. See the
<CODE>textfield()</CODE> section for
details on when these handlers are called.
<H2><A NAME="CREATING_A_SCROLLING_LIST">CREATING A SCROLLING LIST</A></H2>
<P>
<PRE> print $query->scrolling_list('list_name',
['eenie','meenie','minie','moe'],
['eenie','moe'],5,'true');
-or-
</PRE>
<P>
<PRE> print $query->scrolling_list('list_name',
['eenie','meenie','minie','moe'],
['eenie','moe'],5,'true',
\%labels);
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> print $query->scrolling_list(-name=>'list_name',
-values=>['eenie','meenie','minie','moe'],
-default=>['eenie','moe'],
-size=>5,
-multiple=>'true',
-labels=>\%labels);
</PRE>
<P>
<CODE>scrolling_list()</CODE>
creates a scrolling list.
<DL>
<DT><STRONG>Parameters:</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
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.
<P><LI><STRONG>.</STRONG>
The optional third argument (-default) can be either a reference to a list
containing the values to be selected by default, or can be a single value
to select. If this argument is missing or undefined, then nothing is
selected when the list first appears. In the named parameter version, you
can use the synonym ``-defaults'' for this parameter.
<P><LI><STRONG>.</STRONG>
The optional fourth argument is the size of the list (-size).
<P><LI><STRONG>.</STRONG>
The optional fifth argument can be set to true to allow multiple
simultaneous selections (-multiple). Otherwise only one selection will be
allowed at a time.
<P><LI><STRONG>.</STRONG>
The optional sixth argument is a pointer to an associative array containing
long user-visible labels for the list items (-labels). If not provided, the
values will be displayed.
<P>
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:
<P>
<PRE> @selected = $query->param('list_name');
</PRE>
</DL>
<P>
<FONT SIZE=-1>JAVASCRIPTING:</FONT>
<CODE>scrolling_list()</CODE> recognizes the following event handlers:
<STRONG>-onChange</STRONG>, <STRONG>-onFocus</STRONG>, <STRONG>-onMouseOver</STRONG>, <STRONG>-onMouseOut</STRONG>
and <STRONG>-onBlur</STRONG>. See
<CODE>textfield()</CODE> for the
description of when these handlers are called.
<H2><A NAME="CREATING_A_GROUP_OF_RELATED_CHEC">CREATING A GROUP OF RELATED CHECKBOXES</A></H2>
<P>
<PRE> print $query->checkbox_group(-name=>'group_name',
-values=>['eenie','meenie','minie','moe'],
-default=>['eenie','moe'],
-linebreak=>'true',
-labels=>\%labels);
</PRE>
<P>
<PRE> print $query->checkbox_group('group_name',
['eenie','meenie','minie','moe'],
['eenie','moe'],'true',\%labels);
</PRE>
<P>
<PRE> HTML3-COMPATIBLE BROWSERS ONLY:
</PRE>
<P>
<PRE> print $query->checkbox_group(-name=>'group_name',
-values=>['eenie','meenie','minie','moe'],
-rows=2,-columns=>2);
</PRE>
<P>
<CODE>checkbox_group()</CODE>
creates a list of checkboxes that are related by the same name.
<DL>
<DT><STRONG>Parameters:</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
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.
<P><LI><STRONG>.</STRONG>
The optional third argument (-default) can be either a reference to a list
containing the values to be checked by default, or can be a single value to
checked. If this argument is missing or undefined, then nothing is selected
when the list first appears.
<P><LI><STRONG>.</STRONG>
The optional fourth argument (-linebreak) can be set to true to place line
breaks between the checkboxes so that they appear as a vertical list.
Otherwise, they will be strung together on a horizontal line.
<P><LI><STRONG>.</STRONG>
The optional fifth argument is a pointer to an associative array relating
the checkbox values to the user-visible labels that will be printed next to
them (-labels). If not provided, the values will be used as the default.
<P><LI><STRONG>.</STRONG>
<STRONG>HTML3-compatible browsers</STRONG> (such as Netscape) can take advantage of the optional parameters <STRONG>-rows</STRONG>, and <STRONG>-columns</STRONG>. These parameters cause
<CODE>checkbox_group()</CODE> to return an
<FONT SIZE=-1>HTML3</FONT> 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.
<P>
To include row and column headings in the returned table, you can use the <STRONG>-rowheaders</STRONG> and <STRONG>-colheaders</STRONG> 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.
</DL>
<P>
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:
<P>
<PRE> @turned_on = $query->param('group_name');
</PRE>
<P>
The value returned by
<CODE>checkbox_group()</CODE> is
actually an array of button elements. You can capture them and use them
within tables, lists, or in other creative ways:
<P>
<PRE> @h = $query->checkbox_group(-name=>'group_name',-values=>\@values);
&use_in_creative_way(@h);
</PRE>
<P>
<FONT SIZE=-1>JAVASCRIPTING:</FONT>
<CODE>checkbox_group()</CODE> recognizes the
<STRONG>-onClick</STRONG>
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.
<H2><A NAME="CREATING_A_STANDALONE_CHECKBOX">CREATING A STANDALONE CHECKBOX</A></H2>
<P>
<PRE> print $query->checkbox(-name=>'checkbox_name',
-checked=>'checked',
-value=>'ON',
-label=>'CLICK ME');
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> print $query->checkbox('checkbox_name','checked','ON','CLICK ME');
</PRE>
<P>
<CODE>checkbox()</CODE> is used to
create an isolated checkbox that isn't logically related to any others.
<DL>
<DT><STRONG>Parameters:</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
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.
<P><LI><STRONG>.</STRONG>
The optional second parameter (-checked) specifies that the checkbox is
turned on by default. Synonyms are -selected and -on.
<P><LI><STRONG>.</STRONG>
The optional third parameter (-value) specifies the value of the checkbox
when it is checked. If not provided, the word ``on'' is assumed.
<P><LI><STRONG>.</STRONG>
The optional fourth parameter (-label) is the user-readable label to be
attached to the checkbox. If not provided, the checkbox name is used.
</DL>
<P>
The value of the checkbox can be retrieved using:
<P>
<PRE> $turned_on = $query->param('checkbox_name');
</PRE>
<P>
<FONT SIZE=-1>JAVASCRIPTING:</FONT>
<CODE>checkbox()</CODE> recognizes the
<STRONG>-onClick</STRONG>
parameter. See
<CODE>checkbox_group()</CODE> for
further details.
<H2><A NAME="CREATING_A_RADIO_BUTTON_GROUP">CREATING A RADIO BUTTON GROUP</A></H2>
<P>
<PRE> print $query->radio_group(-name=>'group_name',
-values=>['eenie','meenie','minie'],
-default=>'meenie',
-linebreak=>'true',
-labels=>\%labels);
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> print $query->radio_group('group_name',['eenie','meenie','minie'],
'meenie','true',\%labels);
</PRE>
<P>
<PRE> HTML3-COMPATIBLE BROWSERS ONLY:
</PRE>
<P>
<PRE> print $query->radio_group(-name=>'group_name',
-values=>['eenie','meenie','minie','moe'],
-rows=2,-columns=>2);
</PRE>
<P>
<CODE>radio_group()</CODE> creates a
set of logically-related radio buttons (turning one member of the group on
turns the others off)
<DL>
<DT><STRONG>Parameters:</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
The first argument is the name of the group and is required (-name).
<P><LI><STRONG>.</STRONG>
The second argument (-values) is the list of values for the radio buttons.
The values and the labels that appear on the page are identical. Pass an
array <EM>reference</EM> in the second argument, either using an anonymous array, as shown, or by
referencing a named array as in ``\@foo''.
<P><LI><STRONG>.</STRONG>
The optional third parameter (-default) is the name of the default button
to turn on. If not specified, the first item will be the default. You can
provide a nonexistent button name, such as ``-'' to start up with no
buttons selected.
<P><LI><STRONG>.</STRONG>
The optional fourth parameter (-linebreak) can be set to 'true' to put line
breaks between the buttons, creating a vertical list.
<P><LI><STRONG>.</STRONG>
The optional fifth parameter (-labels) is a pointer to an associative array
relating the radio button values to user-visible labels to be used in the
display. If not provided, the values themselves are displayed.
<P><LI><STRONG>.</STRONG>
<STRONG>HTML3-compatible browsers</STRONG> (such as Netscape) can take advantage of the optional parameters <STRONG>-rows</STRONG>, and <STRONG>-columns</STRONG>. These parameters cause
<CODE>radio_group()</CODE> to return an
<FONT SIZE=-1>HTML3</FONT> 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.
<P>
To include row and column headings in the returned table, you can use the <STRONG>-rowheader</STRONG> and <STRONG>-colheader</STRONG> 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.
</DL>
<P>
When the form is processed, the selected radio button can be retrieved
using:
<P>
<PRE> $which_radio_button = $query->param('group_name');
</PRE>
<P>
The value returned by
<CODE>radio_group()</CODE> is
actually an array of button elements. You can capture them and use them
within tables, lists, or in other creative ways:
<P>
<PRE> @h = $query->radio_group(-name=>'group_name',-values=>\@values);
&use_in_creative_way(@h);
</PRE>
<H2><A NAME="CREATING_A_SUBMIT_BUTTON">CREATING A SUBMIT BUTTON</A></H2>
<P>
<PRE> print $query->submit(-name=>'button_name',
-value=>'value');
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> print $query->submit('button_name','value');
</PRE>
<P>
<CODE>submit()</CODE> will create the
query submission button. Every form should have one of these.
<DL>
<DT><STRONG>Parameters:</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
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
<STRONG>never</STRONG> send back a value from a button.
<P><LI><STRONG>.</STRONG>
The second argument (-value) is also optional. This gives the button a
value that will be passed to your script in the query string.
</DL>
<P>
You can figure out which button was pressed by using different values for
each one:
<P>
<PRE> $which_one = $query->param('button_name');
</PRE>
<P>
<FONT SIZE=-1>JAVASCRIPTING:</FONT>
<CODE>radio_group()</CODE> recognizes the
<STRONG>-onClick</STRONG>
parameter. See
<CODE>checkbox_group()</CODE> for
further details.
<H2><A NAME="CREATING_A_RESET_BUTTON">CREATING A RESET BUTTON</A></H2>
<P>
<PRE> print $query->reset
</PRE>
<P>
<CODE>reset()</CODE> creates the ``reset'' button. Note that it restores the form to its value from the last time the script was called,
<FONT SIZE=-1>NOT</FONT> necessarily to the defaults.
<H2><A NAME="CREATING_A_DEFAULT_BUTTON">CREATING A DEFAULT BUTTON</A></H2>
<P>
<PRE> print $query->defaults('button_label')
</PRE>
<P>
<CODE>defaults()</CODE> 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.
<H2><A NAME="CREATING_A_HIDDEN_FIELD">CREATING A HIDDEN FIELD</A></H2>
<P>
<PRE> print $query->hidden(-name=>'hidden_name',
-default=>['value1','value2'...]);
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> print $query->hidden('hidden_name','value1','value2'...);
</PRE>
<P>
<CODE>hidden()</CODE> 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.
<DL>
<DT><STRONG>Parameters:</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
The first argument is required and specifies the name of this field
(-name).
<P><LI><STRONG>.</STRONG>
The second argument is also required and specifies its value (-default). In
the named parameter style of calling, you can provide a single value here
or a reference to a whole list
</DL>
<P>
Fetch the value of a hidden field this way:
<P>
<PRE> $hidden_value = $query->param('hidden_name');
</PRE>
<P>
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:
<P>
<PRE> $query->param('hidden_name','new','values','here');
</PRE>
<H2><A NAME="CREATING_A_CLICKABLE_IMAGE_BUTTO">CREATING A CLICKABLE IMAGE BUTTON</A></H2>
<P>
<PRE> print $query->image_button(-name=>'button_name',
-src=>'/source/URL',
-align=>'MIDDLE');
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> print $query->image_button('button_name','/source/URL','MIDDLE');
</PRE>
<P>
<CODE>image_button()</CODE> 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.
<P>
<FONT SIZE=-1>JAVASCRIPTING:</FONT>
<CODE>image_button()</CODE> recognizes the
<STRONG>-onClick</STRONG>
parameter. See
<CODE>checkbox_group()</CODE> for
further details.
<DL>
<DT><STRONG>Parameters:</STRONG><DD>
<LI><STRONG>.</STRONG>
<P>
The first argument (-name) is required and specifies the name of this
field.
<P><LI><STRONG>.</STRONG>
The second argument (-src) is also required and specifies the
<FONT SIZE=-1>URL</FONT>
<LI><STRONG><A NAME="item_The_third_option_align_option">The third option (-align, optional) is an alignment type, and may be
TOP, BOTTOM or MIDDLE</A></STRONG>
</DL>
<P>
Fetch the value of the button this way: <CODE>$x</CODE> =
$query->param('button_name.x'); <A
HREF="../pod/perlop.html#item__y">$y</A> =
$query->param('button_name.y');
<H2><A NAME="CREATING_A_JAVASCRIPT_ACTION_BUT">CREATING A JAVASCRIPT ACTION BUTTON</A></H2>
<P>
<PRE> print $query->button(-name=>'button_name',
-value=>'user visible label',
-onClick=>"do_something()");
</PRE>
<P>
<PRE> -or-
</PRE>
<P>
<PRE> print $query->button('button_name',"do_something()");
</PRE>
<P>
<CODE>button()</CODE> 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 <STRONG>-onClick</STRONG> parameter will be executed. On non-Netscape browsers this form element will
probably not even display.
<H1><A NAME="NETSCAPE_COOKIES">NETSCAPE COOKIES</A></H1>
<P>
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.
<P>
<FONT SIZE=-1>A</FONT> cookie is a name=value pair much like the named parameters in a
<FONT SIZE=-1>CGI</FONT> query string.
<FONT SIZE=-1>CGI</FONT> scripts create one or more cookies and send them to the browser in the
<FONT SIZE=-1>HTTP</FONT> header. The browser maintains a list of cookies that belong to a particular Web server, and returns them to the
<FONT SIZE=-1>CGI</FONT> script during subsequent interactions.
<P>
In addition to the required name=value pair, each cookie has several
optional attributes:
<OL>
<LI><STRONG><A NAME="item_an_expiration_time">an expiration time</A></STRONG>
<P>
This is a time/date string (in a special
<FONT SIZE=-1>GMT</FONT> 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.
<P><LI><STRONG><A NAME="item_a_domain">a domain</A></STRONG>
This is a partial or complete domain name for which the cookie is valid.
The browser will return the cookie to any host that matches the partial
domain name. For example, if you specify a domain name of
``.capricorn.com'', then Netscape will return the cookie to Web servers
running on any of the machines ``www.capricorn.com'',
``www2.capricorn.com'', ``feckless.capricorn.com'', etc. Domain names must
contain at least two periods to prevent attempts to match on top level
domains like ``.edu''. If no domain is specified, then the browser will
only return the cookie to servers on the host the cookie originated from.
<P><LI><STRONG><A NAME="item_a_path">a path</A></STRONG>
If you provide a cookie path attribute, the browser will check it against your script's
<FONT SIZE=-1>URL</FONT> before returning the cookie. For example, if you specify the path ``/cgi-bin'', then the cookie will be returned to each of the scripts ``/cgi-bin/tally.pl'', ``/cgi-bin/order.pl'', and ``/cgi-bin/customer_service/complain.pl'', but not to the script ``/cgi-private/site_admin.pl''. By default, path is set to ``/'', which causes the cookie to be sent to any
<FONT SIZE=-1>CGI</FONT> script on your site.
<P><LI><STRONG><A NAME="item_a_secure_flag">a "secure" flag</A></STRONG>
If the ``secure'' attribute is set, the cookie will only be sent to your script if the
<FONT SIZE=-1>CGI</FONT> request is occurring on a secure channel, such as
<FONT SIZE=-1>SSL.</FONT>
</OL>
<P>
The interface to Netscape cookies is the <STRONG>cookie()</STRONG> method:
<P>
<PRE> $cookie = $query->cookie(-name=>'sessionID',
-value=>'xyzzy',
-expires=>'+1h',
-path=>'/cgi-bin/database',
-domain=>'.capricorn.org',
-secure=>1);
print $query->header(-cookie=>$cookie);
</PRE>
<P>
<STRONG>cookie()</STRONG> creates a new cookie. Its parameters include:
<DL>
<DT><STRONG><A NAME="item__name">-name</A></STRONG><P>
<DD>
The name of the cookie (required). This can be any string at all. Although
Netscape limits its cookie names to non-whitespace alphanumeric characters,
CGI.pm removes this restriction by escaping and unescaping cookies behind
the scenes.
<P><DT><STRONG><A NAME="item__value">-value</A></STRONG><P>
<DD>
The value of the cookie. This can be any scalar value, array reference, or
even associative array reference. For example, you can store an entire
associative array into a cookie this way:
<P>
<PRE> $cookie=$query->cookie(-name=>'family information',
-value=>\%childrens_ages);
</PRE>
<DT><STRONG>-path</STRONG><P>
<DD>
The optional partial path for which this cookie will be valid, as described
above.
<P><DT><STRONG><A NAME="item__domain">-domain</A></STRONG><P>
<DD>
The optional partial domain for which this cookie will be valid, as
described above.
<P><DT><STRONG><A NAME="item__expires">-expires</A></STRONG><P>
<DD>
The optional expiration date for this cookie. The format is as described in
the section on the <STRONG>header()</STRONG> method:
<P>
<PRE> "+1h" one hour from now
</PRE>
<DT><STRONG><A NAME="item__secure">-secure</A></STRONG><P>
<DD>
If set to true, this cookie will only be used within a secure
<FONT SIZE=-1>SSL</FONT> session.
</DL>
<P>
The cookie created by
<CODE>cookie()</CODE> must be incorporated into the
<FONT SIZE=-1>HTTP</FONT> header within the string returned by the
<CODE>header()</CODE> method:
<P>
<PRE> print $query->header(-cookie=>$my_cookie);
</PRE>
<P>
To create multiple cookies, give
<CODE>header()</CODE> an array reference:
<P>
<PRE> $cookie1 = $query->cookie(-name=>'riddle_name',
-value=>"The Sphynx's Question");
$cookie2 = $query->cookie(-name=>'answers',
-value=>\%answers);
print $query->header(-cookie=>[$cookie1,$cookie2]);
</PRE>
<P>
To retrieve a cookie, request it by name by calling
<CODE>cookie()</CODE> method without the <STRONG>-value</STRONG> parameter:
<P>
<PRE> use CGI;
$query = new CGI;
%answers = $query->cookie(-name=>'answers');
# $query->cookie('answers') will work too!
</PRE>
<P>
The cookie and
<FONT SIZE=-1>CGI</FONT> namespaces are separate. If you have a parameter named 'answers' and a cookie named 'answers', the values retrieved by
<CODE>param()</CODE> and
<CODE>cookie()</CODE> are independent of each other. However, it's simple to turn a
<FONT SIZE=-1>CGI</FONT> parameter into a cookie, and vice-versa:
<P>
<PRE> # 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')]);
</PRE>
<P>
See the <STRONG>cookie.cgi</STRONG> example script for some ideas on how to use cookies effectively.
<P>
<STRONG>NOTE:</STRONG> There appear to be some (undocumented) restrictions on Netscape cookies. In Netscape 2.01, at least,
<FONT SIZE=-1>I</FONT> 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
<FONT SIZE=-1>ID,</FONT> store it in a cookie, and use the session
<FONT SIZE=-1>ID</FONT> to locate an external file/database saved on the server's side of the connection.
<H1><A NAME="WORKING_WITH_NETSCAPE_FRAMES">WORKING WITH NETSCAPE FRAMES</A></H1>
<P>
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:
<OL>
<LI><STRONG><A NAME="item_Create_a_Frameset_document">Create a <Frameset> document</A></STRONG>
<P>
After writing out the
<FONT SIZE=-1>HTTP</FONT> header, instead of creating a standard
<FONT SIZE=-1>HTML</FONT> document using the
<CODE>start_html()</CODE> call, create a
<FONT SIZE=-1><FRAMESET></FONT> document that defines the frames on the page. Specify your
<CODE>script(s)</CODE> (with appropriate parameters) as the
<FONT SIZE=-1>SRC</FONT> for each of the frames.
<P>
There is no specific support for creating
<FONT SIZE=-1><FRAMESET></FONT> sections in CGI.pm, but the
<FONT SIZE=-1>HTML</FONT> is very simple to write. See the frame documentation in Netscape's home pages for details
<P>
<PRE> [perlman:lib:frames|frames]
</PRE>
<LI><STRONG><A NAME="item_Specify_the_destination_for_the_">Specify the destination for the document in the HTTP header</A></STRONG>
<P>
You may provide a <STRONG>-target</STRONG> parameter to the
<CODE>header()</CODE> method: print
$q->header(-target=>'ResultsWindow');
<P>
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.
<P><LI><STRONG><A NAME="item_Specify_the_destination_for_the_">Specify the destination for the document in the <FORM> tag</A></STRONG>
You can specify the frame to load in the
<FONT SIZE=-1>FORM</FONT> tag itself. With CGI.pm it looks like this:
<P>
<PRE> print $q->startform(-target=>'ResultsWindow');
</PRE>
<P>
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.
</OL>
<P>
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.
<H1><A NAME="LIMITED_SUPPORT_FOR_CASCADING_ST">LIMITED SUPPORT FOR CASCADING STYLE SHEETS</A></H1>
<P>
CGI.pm has limited support for HTML3's cascading style sheets (css). To incorporate a stylesheet into your document, pass the
<CODE>start_html()</CODE> method a
<STRONG>-style</STRONG> parameter. The value of this parameter may be a scalar, in which case it is
incorporated directly into a <
<FONT SIZE=-1>STYLE></FONT> section, or it may be a hash reference. In
the latter case you should provide the hash with one or more of <STRONG>-src</STRONG> or
<STRONG>-code</STRONG>. <STRONG>-src</STRONG> points to a
<FONT SIZE=-1>URL</FONT> where an externally-defined stylesheet can be
found. <STRONG>-code</STRONG> points to a scalar value to be incorporated into a <
<FONT SIZE=-1>STYLE></FONT> section. Style definitions in <STRONG>-code</STRONG>
override similarly-named ones in <STRONG>-src</STRONG>, hence the name ``cascading.''
<P>
You may also specify the type of the stylesheet by adding the optional
<STRONG>-type</STRONG> parameter to the hash pointed to by <STRONG>-style</STRONG>. If not specified, the style defaults to 'text/css'.
<P>
To refer to a style within the body of your document, add the
<STRONG>-class</STRONG> parameter to any
<FONT SIZE=-1>HTML</FONT> element:
<P>
<PRE> print h1({-class=>'Fancy'},'Welcome to the Party');
</PRE>
<P>
Or define styles on the fly with the <STRONG>-style</STRONG> parameter:
<P>
<PRE> print h1({-style=>'Color: red;'},'Welcome to Hell');
</PRE>
<P>
You may also use the new <STRONG>span()</STRONG> element to apply a style to a section of text:
<P>
<PRE> print span({-style=>'Color: red;'},
h1('Welcome to Hell'),
"Where did that handbasket get to?"
);
</PRE>
<P>
Note that you must import the ``:html3'' definitions to have the
<STRONG>span()</STRONG> method available. Here's a quick and dirty example of using CSS's. See the
<FONT SIZE=-1>CSS</FONT> specification at <A
HREF="http://www.w3.org/pub/WWW/TR/Wd-css-1.html">http://www.w3.org/pub/WWW/TR/Wd-css-1.html</A>
for more information.
<P>
<PRE> use CGI qw/:standard :html3/;
</PRE>
<P>
<PRE> #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=>'<A HREF="http://www.capricorn.com/style/st1.css">http://www.capricorn.com/style/st1.css</A>',
-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;
</PRE>
<H1><A NAME="DEBUGGING">DEBUGGING</A></H1>
<P>
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:
<P>
<PRE> your_script.pl keyword1 keyword2 keyword3
</PRE>
<P>
or this:
<P>
<PRE> your_script.pl keyword1+keyword2+keyword3
</PRE>
<P>
or this:
<P>
<PRE> your_script.pl name1=value1 name2=value2
</PRE>
<P>
or this:
<P>
<PRE> your_script.pl name1=value1&name2=value2
</PRE>
<P>
or even as newline-delimited parameters on standard input.
<P>
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:
<P>
<PRE> your_script.pl "name1='I am a long value'" "name2=two\ words"
</PRE>
<H2><A NAME="DUMPING_OUT_ALL_THE_NAME_VALUE_P">DUMPING OUT ALL THE NAME/VALUE PAIRS</A></H2>
<P>
The
<CODE>dump()</CODE> 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:
<P>
<PRE> print $query->dump
</PRE>
<P>
Produces something that looks like:
<P>
<PRE> <UL>
<LI>name1
<UL>
<LI>value1
<LI>value2
</UL>
<LI>name2
<UL>
<LI>value1
</UL>
</UL>
</PRE>
<P>
You can pass a value of 'true' to
<CODE>dump()</CODE> in order to get it to print the results out as plain text, suitable for incorporating into a
<FONT SIZE=-1><PRE></FONT> section.
<P>
As a shortcut, as of version 1.56 you can interpolate the entire
<FONT SIZE=-1>CGI</FONT> object into a string and it will be replaced with the a nice
<FONT SIZE=-1>HTML</FONT> dump shown above:
<P>
<PRE> $query=new CGI;
print "<H2>Current Values</H2> $query\n";
</PRE>
<H1><A NAME="FETCHING_ENVIRONMENT_VARIABLES">FETCHING ENVIRONMENT VARIABLES</A></H1>
<P>
Some of the more useful environment variables can be fetched through this
interface. The methods are as follows:
<DL>
<DT><STRONG><A NAME="item_accept">accept()</A></STRONG><P>
<DD>
Return a list of
<FONT SIZE=-1>MIME</FONT> types that the remote browser accepts. If you give this method a single argument corresponding to a
<FONT SIZE=-1>MIME</FONT> type, as in $query->accept('text/html'), it will return a floating point value corresponding to the browser's preference for this type from 0.0 (don't want) to 1.0. Glob types (e.g. text/*) in the browser's accept list are handled correctly.
<P><DT><STRONG><A NAME="item_raw_cookie">raw_cookie()</A></STRONG><P>
<DD>
Returns the
<FONT SIZE=-1>HTTP_COOKIE</FONT> variable, an
<FONT SIZE=-1>HTTP</FONT> extension implemented by Netscape browsers version 1.1 and higher. Cookies have a special format, and this method call just returns the raw form (?cookie dough). See
<CODE>cookie()</CODE> for ways of setting and retrieving cooked cookies.
<P>
Called with no parameters,
<CODE>raw_cookie()</CODE> 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 <STRONG>unescaped</STRONG> form of the cookie. You can use the regular
<CODE>cookie()</CODE> method to get the names, or use the
<CODE>raw_fetch()</CODE> method from the CGI::Cookie module.
<P><DT><STRONG><A NAME="item_user_agent">user_agent()</A></STRONG><P>
<DD>
Returns the
<FONT SIZE=-1>HTTP_USER_AGENT</FONT> variable. If you give this method a
single argument, it will attempt to pattern match on it, allowing you to do
something like $query->user_agent(netscape);
<P><DT><STRONG><A NAME="item_path_info">path_info()</A></STRONG><P>
<DD>
Returns additional path information from the script
<FONT SIZE=-1>URL.</FONT>
<FONT SIZE=-1>E.G.</FONT> fetching /cgi-bin/your_script/additional/stuff will result in $query->path_info() returning ``additional/stuff''.
<P>
<FONT SIZE=-1>NOTE:</FONT> The Microsoft Internet Information Server is broken with respect to additional path information. If you use the Perl
<FONT SIZE=-1>DLL</FONT> library, the
<FONT SIZE=-1>IIS</FONT> 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
<FONT SIZE=-1>CGI</FONT> scripts destined for use with
<FONT SIZE=-1>IIS.</FONT>
<P><DT><STRONG><A NAME="item_path_translated">path_translated()</A></STRONG><P>
<DD>
As per
<CODE>path_info()</CODE> but returns
the additional path information translated into a physical path, e.g.
``/usr/local/etc/httpd/htdocs/additional/stuff''.
<P>
The Microsoft
<FONT SIZE=-1>IIS</FONT> is broken with respect to the translated path as
well.
<P><DT><STRONG><A NAME="item_remote_host">remote_host()</A></STRONG><P>
<DD>
Returns either the remote host name or
<FONT SIZE=-1>IP</FONT> address. if the former is unavailable.
<P><DT><STRONG><A NAME="item_script_name">script_name()
Return the script name as a partial URL, for self-refering
scripts.</A></STRONG><DD>
<DT><STRONG><A NAME="item_referer">referer()</A></STRONG><P>
<DD>
Return the
<FONT SIZE=-1>URL</FONT> of the page the browser was viewing prior to
fetching your script. Not available for all browsers.
<P><DT><STRONG><A NAME="item_auth_type">auth_type ()</A></STRONG><P>
<DD>
Return the authorization/verification method in use for this script, if
any.
<P><DT><STRONG><A NAME="item_server_name">server_name ()</A></STRONG><P>
<DD>
Returns the name of the server, usually the machine's host name.
<P><DT><STRONG><A NAME="item_virtual_host">virtual_host ()</A></STRONG><P>
<DD>
When using virtual hosts, returns the name of the host that the browser
attempted to contact
<P><DT><STRONG><A NAME="item_server_software">server_software ()</A></STRONG><P>
<DD>
Returns the server software and version number.
<P><DT><STRONG><A NAME="item_remote_user">remote_user ()</A></STRONG><P>
<DD>
Return the authorization/verification name used for user verification, if
this script is protected.
<P><DT><STRONG><A NAME="item_user_name">user_name ()</A></STRONG><P>
<DD>
Attempt to obtain the remote user's name, using a variety of different
techniques. This only works with older browsers such as Mosaic. Netscape
does not reliably report the user name!
<P><DT><STRONG><A NAME="item_request_method">request_method()</A></STRONG><P>
<DD>
Returns the method used to access your script, usually one of
<FONT SIZE=-1>'POST',</FONT>
<FONT SIZE=-1>'GET'</FONT> or
<FONT SIZE=-1>'HEAD'.</FONT>
</DL>
<H1><A NAME="USING_NPH_SCRIPTS">USING NPH SCRIPTS</A></H1>
<P>
<FONT SIZE=-1>NPH,</FONT> or ``no-parsed-header'', scripts bypass the server completely by sending the complete
<FONT SIZE=-1>HTTP</FONT> header directly to the browser. This has slight performance benefits, but is of most use for taking advantage of
<FONT SIZE=-1>HTTP</FONT> extensions that are not directly supported by your server, such as server push and
<FONT SIZE=-1>PICS</FONT> headers.
<P>
Servers use a variety of conventions for designating
<FONT SIZE=-1>CGI</FONT> scripts as
<FONT SIZE=-1>NPH.</FONT> 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
<FONT SIZE=-1>NPH</FONT> script by examining the first line of script output.
<P>
CGI.pm supports
<FONT SIZE=-1>NPH</FONT> scripts with a special
<FONT SIZE=-1>NPH</FONT> mode. When in this mode, CGI.pm will output the necessary extra header information when the
<CODE>header()</CODE> and
<CODE>redirect()</CODE> methods are called.
<P>
The Microsoft Internet Information Server requires
<FONT SIZE=-1>NPH</FONT> mode. As of version 2.30, CGI.pm will automatically detect when the script is running under
<FONT SIZE=-1>IIS</FONT> and put itself into this mode. You do not need to do this manually, although it won't hurt anything if you do.
<P>
There are a number of ways to put CGI.pm into
<FONT SIZE=-1>NPH</FONT> mode:
<DL>
<DT><STRONG><A NAME="item_In">In the use statement</A></STRONG><P>
<DD>
Simply add the ``-nph'' pragmato the list of symbols to be imported into
your script:
<P>
<PRE> use CGI qw(:standard -nph)
</PRE>
<DT><STRONG><A NAME="item_By">By calling the nph() method:</A></STRONG><P>
<DD>
Call <STRONG>nph()</STRONG> with a non-zero parameter at any point after using CGI.pm in your program.
<P>
<PRE> CGI->nph(1)
</PRE>
<DT><STRONG>By using -nph parameters in the header() and redirect() statements:</STRONG><P>
<DD>
<PRE> print $q->header(-nph=>1);
</PRE>
</DL>
<H1><A NAME="Server_Push">Server Push</A></H1>
<P>
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 <<A HREF="mailto:ed@fidalgo.net">ed@fidalgo.net</A>> To import these into your namespace, you must import the ``:push'' set. You are also advised to put the script into
<FONT SIZE=-1>NPH</FONT> mode and to set $| to 1 to avoid buffering problems.
<P>
Here is a simple script that demonstrates server push:
<P>
<PRE> #!/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;
}
</PRE>
<P>
This script initializes server push by calling <STRONG>multipart_init()</STRONG>. It then enters an infinite loop in which it begins a new multipart
section by calling <STRONG>multipart_start()</STRONG>, prints the current local time, and ends a multipart section with <STRONG>multipart_end()</STRONG>. It then sleeps a second, and begins again.
<DL>
<DT><STRONG><A NAME="item_multipart_init">multipart_init()
multipart_init(-boundary=>$boundary);</A></STRONG><P>
<DD>
Initialize the multipart system. The -boundary argument specifies what
<FONT SIZE=-1>MIME</FONT> boundary string to use to separate parts of the
document. If not provided, CGI.pm chooses a reasonable boundary for you.
<P><DT><STRONG><A NAME="item_multipart_start">multipart_start()</A></STRONG><P>
<DD>
<PRE> multipart_start(-type=>$type)
</PRE>
<P>
Start a new part of the multipart document using the specified
<FONT SIZE=-1>MIME</FONT> type. If not specified, text/html is assumed.
<P><DT><STRONG><A NAME="item_multipart_end">multipart_end()</A></STRONG><P>
<DD>
<PRE> multipart_end()
</PRE>
<P>
End a part. You must remember to call
<CODE>multipart_end()</CODE> once for each
<CODE>multipart_start().</CODE>
</DL>
<P>
Users interested in server push applications should also have a look at the
CGI::Push module.
<H1><A NAME="Avoiding_Denial_of_Service_Attac">Avoiding Denial of Service Attacks</A></H1>
<P>
<FONT SIZE=-1>A</FONT> potential problem with CGI.pm is that, by default, it attempts to process form POSTings no matter how large they are.
<FONT SIZE=-1>A</FONT> wily hacker could attack your site by sending a
<FONT SIZE=-1>CGI</FONT> script a huge
<FONT SIZE=-1>POST</FONT> of many megabytes. CGI.pm will attempt to read the entire
<FONT SIZE=-1>POST</FONT> 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.
<P>
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.
<P>
The best way to avoid denial of service attacks is to limit the amount of memory,
<FONT SIZE=-1>CPU</FONT> time and disk space that
<FONT SIZE=-1>CGI</FONT> scripts can use. Some Web servers come with built-in facilities to accomplish this. In other cases, you can use the shell
<EM>limit</EM> or <EM>ulimit</EM>
commands to put ceilings on
<FONT SIZE=-1>CGI</FONT> resource usage.
<P>
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
<FONT SIZE=-1>CGI</FONT> name space:
<DL>
<DT><STRONG><A NAME="item__CGI_POST_MAX">$CGI::POST_MAX</A></STRONG><P>
<DD>
If set to a non-negative integer, this variable puts a ceiling on the size of POSTings, in bytes. If CGI.pm detects a
<FONT SIZE=-1>POST</FONT> that is greater than the ceiling, it will immediately exit with an error message. This value will affect both ordinary POSTs and multipart POSTs, meaning that it limits the maximum size of file uploads as well. You should set this to a reasonably high value, such as 1 megabyte.
<P><DT><STRONG><A NAME="item__CGI_DISABLE_UPLOADS">$CGI::DISABLE_UPLOADS</A></STRONG><P>
<DD>
If set to a non-zero value, this will disable file uploads completely.
Other fill-out form values will work as usual.
</DL>
<P>
You can use these variables in either of two ways.
<OL>
<LI><STRONG><A NAME="item_On_a_script_by_script_basis">On a script-by-script basis</A></STRONG>
<P>
Set the variable at the top of the script, right after the ``use''
statement:
<P>
<PRE> use CGI qw/:standard/;
use CGI::Carp 'fatalsToBrowser';
$CGI::POST_MAX=1024 * 100; # max 100K posts
$CGI::DISABLE_UPLOADS = 1; # no uploads
</PRE>
<LI><STRONG><A NAME="item_Globally_for_all_scripts">Globally for all scripts</A></STRONG>
<P>
Open up CGI.pm, find the definitions for <CODE>$POST_MAX</CODE> and
<FONT SIZE=-1>$DISABLE_UPLOADS,</FONT> and set them to the desired values. You'll find them towards the top of the file in a subroutine named
<CODE>initialize_globals().</CODE>
</OL>
<P>
Since an attempt to send a
<FONT SIZE=-1>POST</FONT> larger than <CODE>$POST_MAX</CODE> 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 [perlman:CGI::Carp|CGI::Carp] manual page for more details.
<H1><A NAME="COMPATIBILITY_WITH_CGI_LIB_PL">COMPATIBILITY WITH CGI-LIB.PL</A></H1>
<P>
To make it easier to port existing programs that use cgi-lib.pl the
compatibility routine ``ReadParse'' is provided. Porting is simple:
<P>
<FONT SIZE=-1>OLD</FONT>
<FONT SIZE=-1>VERSION</FONT> require ``cgi-lib.pl''; &ReadParse; print ``The value of the antique is $in{antique}.\n'';
<P>
<FONT SIZE=-1>NEW</FONT>
<FONT SIZE=-1>VERSION</FONT> use
<FONT SIZE=-1>CGI;</FONT> CGI::ReadParse print ``The value of the antique is $in{antique}.\n'';
<P>
CGI.pm's
<CODE>ReadParse()</CODE> 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
<CODE>@in</CODE> and <CODE>$in</CODE> variables, are not supported.
<P>
Once you use ReadParse, you can retrieve the query object itself this way:
<P>
<PRE> $q = $in{CGI};
print $q->textfield(-name=>'wow',
-value=>'does this really work?');
</PRE>
<P>
This allows you to start using the more interesting features of CGI.pm
without rewriting your old scripts from scratch.
<H1><A NAME="AUTHOR_INFORMATION">AUTHOR INFORMATION</A></H1>
<P>
Copyright 1995-1997, Lincoln
<FONT SIZE=-1>D.</FONT> Stein. All rights reserved. It may be used and modified freely, but
<FONT SIZE=-1>I</FONT> 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.
<P>
Address bug reports and comments to: <A
HREF="mailto:lstein@genome.wi.mit.edu">lstein@genome.wi.mit.edu</A>
<H1><A NAME="CREDITS">CREDITS</A></H1>
<P>
Thanks very much to:
<DL>
<DT><STRONG><A NAME="item_Matt">Matt Heffron (heffron@falstaff.css.beckman.com)</A></STRONG><DD>
<DT><STRONG><A NAME="item_James">James Taylor (james.taylor@srs.gov)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Scott">Scott Anguish <sanguish@digifix.com></A></STRONG><DD>
<DT><STRONG><A NAME="item_Mike">Mike Jewell (mlj3u@virginia.edu)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Timothy">Timothy Shimmin (tes@kbs.citri.edu.au)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Joergen">Joergen Haegg (jh@axis.se)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Laurent">Laurent Delfosse (delfosse@csgrad1.cs.wvu.edu)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Richard">Richard Resnick (applepi1@aol.com)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Craig">Craig Bishop (csb@barwonwater.vic.gov.au)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Tony">Tony Curtis (tc@vcpc.univie.ac.at)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Tim">Tim Bunce (Tim.Bunce@ig.co.uk)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Tom">Tom Christiansen (tchrist@convex.com)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Andreas">Andreas Koenig (k@franz.ww.TU-Berlin.DE)</A></STRONG><DD>
<DT><STRONG>Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au)</STRONG><DD>
<DT><STRONG><A NAME="item_Kevin">Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Stephen">Stephen Dahmen (joyfire@inxpress.net)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Ed">Ed Jordan (ed@fidalgo.net)</A></STRONG><DD>
<DT><STRONG><A NAME="item_David">David Alan Pisoni (david@cnation.com)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Doug">Doug MacEachern (dougm@opengroup.org)</A></STRONG><DD>
<DT><STRONG><A NAME="item_Robin">Robin Houston (robin@oneworld.org)</A></STRONG><DD>
<DT><STRONG><A NAME="item__and">...and many many more...</A></STRONG><P>
<DD>
for suggestions and bug fixes.
</DL>
<H1><A NAME="A_COMPLETE_EXAMPLE_OF_A_SIMPLE_F">A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT</A></H1>
<P>
<PRE> #!/usr/local/bin/perl
use CGI;
$query = new CGI;
</PRE>
<P>
<PRE> 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);
</PRE>
<P>
<PRE> print "<H2>Here are the current settings in this form</H2>";
</PRE>
<P>
<PRE> 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
}
</PRE>
<H1><A NAME="BUGS">BUGS</A></H1>
<P>
This module has grown large and monolithic. Furthermore it's doing many things, such as handling URLs, parsing
<FONT SIZE=-1>CGI</FONT> input, writing
<FONT SIZE=-1>HTML,</FONT> etc., that are also done in the
<FONT SIZE=-1>LWP</FONT> modules. It should be discarded in favor of the
<FONT SIZE=-1>CGI::*</FONT> modules, but somehow
<FONT SIZE=-1>I</FONT> continue to work on it.
<P>
Note that the code is truly contorted in order to avoid spurious warnings
when programs are run with the <STRONG>-w</STRONG> switch.
<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
<P>
[perlman:CGI::Carp|CGI::Carp], <EM>URI</EM>, [perlman:CGI::Request|CGI::Request], [perlman:CGI::MiniSvr|CGI::MiniSvr],
[perlman:CGI::Base|CGI::Base], [perlman:CGI::Form|CGI::Form], [perlman:CGI::Apache|CGI::Apache], [perlman:CGI::Switch|CGI::Switch],
[perlman:CGI::Push|CGI::Push], [perlman:CGI::Fast|CGI::Fast]
</DL>
<HR>
<H1>DISCLAIMER</H1>
We are painfully aware that these documents may contain incorrect links and
misformatted HTML. Such bugs lie in the automatic translation process
that automatically created the hundreds and hundreds of separate documents that you find here. Please <B>do
not report</B> link or formatting bugs, because we cannot fix
per-document problems. The only bug reports that will help us are those
that supply working patches to the <I>installhtml</I> or <I>pod2html</I>
programs, or to the <TT>Pod::HTML</TT> module itself, for which I and the entire
Perl community will shower you with thanks and praises.
<P>
If rather than formatting bugs, you encounter substantive content errors in these documents, such as mistakes in
the explanations or code, please use the <I>perlbug</I> utility included
with the Perl distribution.
<P>
<DL><DD>--Tom Christiansen, Perl Documentation Compiler and Editor</DL>
<P>
<HR>
Return to the [perlman:lib:index|index].
<BR>
Return to the <A HREF="http://www.perl.com/">Perl Home Page</A>.
</BODY>
</HTML>