![[logo]](examples/dna.small.gif) CGI.pm - a Perl5 CGI Library
CGI.pm - a Perl5 CGI Library
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 can then ask the CGI object to return or modify the query values. CGI objects handle POST and GET methods correctly, and correctly 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:
#!/usr/local/bin/perl
use CGI qw(:standard);
print header;
print start_html('A Simple Example'),
    h1('A Simple Example'),
    start_form,
    "What's your name? ",textfield('name'),
    p,
    "What's the combination?",
    p,
    checkbox_group(-name=>'words',
		   -values=>['eenie','meenie','minie','moe'],
		   -defaults=>['eenie','minie']),
    p,
    "What's your favorite color? ",
    popup_menu(-name=>'color',
	       -values=>['red','green','blue','chartreuse']),
    p,
    submit,
    end_form,
    hr;
if (param()) {
    print 
	"Your name is",em(param('name')),
	p,
	"The keywords are: ",em(join(", ",param('words'))),
	p,
	"Your favorite color is ",em(param('color')),
	hr;
}
print end_html;
Select this link to try the script
The current version of the software can always be downloaded from the master copy of this document maintained at http://stein.cshl.org/WWW/software/CGI/.
This package requires perl 5.004 or higher. Earlier versions of Perl may work, but CGI.pm has not been tested with them. If you're really stuck, edit the source code to remove the line that says "require 5.004", but don't be surprised if you run into problems.
If you are using a Unix system, you should have perl do the installation for you. Move to the directory containing CGI.pm and type the following commands:
% perl Makefile.PL % make % make installYou may need to be root to do the last step.
This will create two new files in your Perl library. CGI.pm is the main library file. Carp.pm (in the subdirectory "CGI") contains some optional utility routines for writing nicely formatted error messages into your server logs. See the Carp.pm man page for more details.
If you get error messages when you try to install, then you are either:
> cd CGI.pm-2.73 > copy CGI.pm C:\Perl\lib > mkdir C:\Perl\lib\CGI > copy CGI\*.pm C:\Perl\lib\CGIModify this recipe if your Perl library has a different location.
For Macintosh users, just drag the file named CGI.pm into the folder where your other Perl .pm files are stored. Also drag the subfolder named "CGI".
If you do not have sufficient privileges to install into /usr/local/lib/perl5, you can still use CGI.pm. Modify the installation recipe as follows:
% perl Makefile.PL INSTALLDIRS=site INSTALLSITELIB=/home/your/private/dir % make % make installReplace /home/your/private/dir with the full path to the directory you want the library placed in. Now preface your CGI scripts with a preamble something like the following:
Be sure to replace /home/your/private/dir with the true location of CGI.pm.use lib '/home/your/private/dir'; use CGI;
Notes on using CGI.pm in NT and other non-Unix platforms
#!/usr/local/bin/perl
use CGI qw/:standard/;
print header(),
      start_html(-title=>'Wow!'),
      h1('Wow!'),
      'Look Ma, no hands!',
      end_html();
In addition to the standard set, there are many optional sets of less frequently used CGI functions. See Importing CGI Methods for full details.
In the object-oriented mode, you use CGI; without specifying any functions or function sets to import. In this case, you communicate with CGI.pm via a CGI object. The object is created by a call to CGI::new() and encapsulates all the state information about the current CGI transaction, such as values of the CGI parameters passed to your script. Although more verbose, this coding style has the advantage of allowing you to create multiple CGI objects, save their state to disk or to a database, and otherwise manipulate them to achieve neat effects.
The same script written using the object-oriented style looks like this:
#!/usr/local/bin/perl
use CGI;
$q = new CGI;
print $q->header(),
      $q->start_html(-title=>'Wow!'),
      $q->h1('Wow!'),
      'Look Ma, no hands!',
      $q->end_html();
Many of the code examples below show the object-oriented coding style. Mentally translate them into the function-oriented style if you prefer.
    use CGI;
    $query = new CGI;
In the object-oriented world of Perl 5, this code calls the new()
method of the CGI class and stores a new CGI object into the variable
named $query.  The new() method does all the dirty work of parsing
the script parameters and environment variables and stores its results
in the new object.  You'll now make method calls with this object to
get at the parameters, generate form elements, and do other useful things.
An alternative form of the new() method allows you to read script parameters from a previously-opened file handle:
    $query = new CGI(FILEHANDLE)
The filehandle can contain a URL-encoded query string, or can be a
series of newline delimited TAG=VALUE pairs.  This is compatible with
the save() method.  This lets you save the state of a CGI script to a
file and reload it later.  It's also possible to save the contents of
several query objects to the same file, either within a single script
or over a period of time.  You can then reload the multiple records
into an array of query objects with something like this:
open (IN,"test.in") || die;
while (!eof(IN)) {
    my $q = new CGI(IN);
    push(@queries,$q);
}
    my $q = new CGI(\*IN);
If you are using the function-oriented interface and want to initialize CGI state from a file handle, the way to do this is with restore_parameters(). This will (re)initialize the default CGI object from the indicated file handle.
open (IN,"test.in") || die; restore_parameters(IN); close IN;
You can initialize a CGI object from an associative-array reference. Values can be either single- or multivalued:
$query = new CGI({'dinosaur'=>'barney',
                  'song'=>'I love you',
                  'friends'=>[qw/Jessica George Nancy/]});
$query = new CGI('dinosaur=barney&color=purple');
$old_query = new CGI; $new_query = new CGI($old_query);
This form also allows you to create a CGI object that is initially empty:
$empty_query = new CGI('');
If you are using mod_perl, you can initialize a CGI object at any stage of the request by passing the request object to CGI->new:
$q = CGI->new($r);
To do this with the function-oriented interface, set Apache->request($r) before calling the first CGI function.
Finally, you can pass code reference to new() in order to install an upload_hook function that will be called regularly while a long file is being uploaded. See Creating a File Upload Field for details.
See advanced techniques for more information.
    @keywords = $query->keywords
If the script was invoked as the result of an <ISINDEX> search, the
parsed keywords can be obtained with the keywords() method.  This method
will return the keywords as a perl array.
    @names = $query->param  If the script was invoked with a
parameter list
(e.g. "name1=value1&name2=value2&name3=value3"), the param()
method will return the parameter names as a list.  For backwards
compatibility if the script was invoked as an <ISINDEX> script
and contains a string without ampersands (e.g. "value1+value2+value3")
, there will be a single parameter named "keywords" containing the
"+"-delimited keywords.
   @values = $query->param('foo');
             -or-
   $value = $query->param('foo');
Pass the param() method a single argument to fetch the value of the
named parameter. If the parameter is multivalued (e.g. from multiple
selections in a scrolling list), you can ask to receive an array.  Otherwise
the method will return a single value.
If a value is not given in the query string, as in the queries "name1=&name2=" or "name1&name2", it will be returned as an empty string (not undef). This feature is new in 2.63, and was introduced to avoid multiple "undefined value" warnings when running with the -w switch.
If the parameter does not exist at all, then param() will return undef in a scalar context, and the empty list in a list context.
   $query->param('foo','an','array','of','values');
                   -or-
   $query->param(-name=>'foo',-values=>['an','array','of','values']);
This sets the value for the named parameter 'foo' to one or more
values.  These values will be used to initialize form elements, if
you so desire.  Note that this is the one way to forcibly change the value
of a form field after it has previously been set.
The second example shows an alternative "named parameter" style of function call that is accepted by most of the CGI methods. See Calling CGI functions that Take Multiple Arguments for an explanation of this style.
$query->append(-name=>'foo',-values=>['yet','more','values']);This adds a value or list of values to the named parameter. The values are appended to the end of the parameter if it already exists. Otherwise the parameter is created.
   $query->delete('foo');
This 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.
$query->delete_all();This deletes all the parameters and leaves you with an empty CGI object. This may be useful to restore all the defaults produced by the form element generating methods.
If POSTed data is not of type application/x-www-form-urlencoded or multipart/form-data, then the POSTed data will not be processed, but instead be returned as-is in a parameter named POSTDATA. To retrieve it, use code like this:
   my $data = $query->param('POSTDATA');
(If you don't know what the preceding means, don't worry about it.  It
only affects people trying to use CGI for XML processing and other
specialized tasks.)
   $query->import_names('R');
   print "Your name is $R::name\n"
   print "Your favorite colors are @R::colors\n";
This imports all parameters into the given name space.  For example,
if there were parameters named 'foo1', 'foo2' and 'foo3', after
executing $query->import_names('R'), the variables
@R::foo1, $R::foo1, @R::foo2, $R::foo2, etc. would
conveniently spring into existence.  Since CGI has no way of
knowing whether you expect a multi- or single-valued parameter,
it creates two variables for each parameter.  One is an array,
and contains all the values, and the other is a scalar containing
the first member of the array.  Use whichever one is appropriate.
For keyword (a+b+c+d) lists, the variable @R::keywords will be
created.
If you don't specify a name space, this method assumes namespace "Q".
An optional second argument to import_names, if present and non-zero, will delete the contents of the namespace before loading it. This may be useful for environments like mod_perl in which the script does not exit after processing a request.
Warning: do not import into namespace 'main'. This represents a major security risk, as evil people could then use this feature to redefine central variables such as @INC. CGI.pm will exit with an error if you try to do this.
NOTE: Variable names are transformed as necessary into legal Perl variable names. All non-legal characters are transformed into underscores. If you need to keep the original names, you should use the param() method instead to access CGI variables by name.
$q->param_fetch('address')->[1] = '1313 Mockingbird Lane';
unshift @{$q->param_fetch(-name=>'address')},'George Munster';
You may call param_fetch() with the name of the CGI parameter, or with the -name argument, which has the same meaning as elsewhere.
$params = $q->Vars;
print $params->{'address'};
@foo = split("\0",$params->{'foo'});
%params = $q->Vars;
use CGI ':cgi-lib';
$params = Vars;
Many people want to fetch the entire parameter list as a hash in which the keys are the names of the CGI parameters, and the values are the parameters' values. The Vars() method does this. Called in a scalar context, it returns the parameter list as a tied hash reference. Changing a key changes the value of the parameter in the underlying CGI parameter list. Called in an list context, it returns the parameter list as an ordinary hash. This allows you to read the contents of the parameter list, but not to change it.
When using this, the thing you must watch out for are multivalued CGI parameters. Because a hash cannot distinguish between scalar and list context, multivalued parameters will be returned as a packed string, separated by the "\0" (null) character. You must split this packed string in order to get at the individual values. This is the convention introduced long ago by Steve Brenner in his cgi-lib.pl module for Perl version 4.
If you wish to use Vars() as a function, import the :cgi-lib set of function calls (also see the section on CGI-LIB compatibility).
Errors can occur while processing user input, particularly when processing uploaded files. When these errors occur, CGI will stop processing and return an empty parameter list. You can test for the existence and nature of errors using the cgi_error() function. The error messages are formatted as HTTP status codes. You can either incorporate the error text into an HTML page, or use it as the value of the HTTP status:
    my $error = $q->cgi_error;
    if ($error) {
	print $q->header(-status=>$error),
	      $q->start_html('Problems'),
              $q->h2('Request not processed'),
	      $q->strong($error);
        exit 0;
    }
When using the function-oriented interface (see the next section), errors may only occur the first time you call param(). Be prepared for this! Table of contents
$query->save(\*FILEHANDLE)This writes the current query out to the file handle of your choice. The file handle must already be open and be 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 at some later time. You can write out multiple queries to the same file and later read them into query objects one by one.
If you wish to use this method from the function-oriented (non-OO) interface, the exported name for this method is save_parameters(). See advanced techniques for more information.
$my_url=$query->self_urlThis call returns a URL that, when selected, reinvokes this script 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). See advanced techniques for an example.
If you'd like to get the URL without the entire query string appended to
it, use the url() method:
$my_self=$query->url
    $full_url      = $query->url();
    $full_url      = $query->url(-full=>1);  #alternative syntax
    $relative_url  = $query->url(-relative=>1);
    $absolute_url  = $query->url(-absolute=>1);
    $url_with_path = $query->url(-path_info=>1);
    $url_with_path_and_query = $query->url(-path_info=>1,-query=>1);
url() returns the script's URL in a variety of formats.
Called without any arguments, it returns the full form of the URL,
including host name and port number
http://your.host.com/path/to/script.cgiYou can modify this format with the following named arguments:
/path/to/script.cgi
      
      
    script.cgi
      
   $color = $query->url_param('color');
It is possible for a script to receive CGI parameters in the URL as
well as in the fill-out form by creating a form that POSTs to a URL
containing a query string (a "?" mark followed by arguments).  The
param() method will always return the contents of the POSTed
fill-out form, ignoring the URL's query string.  To retrieve URL
parameters, call the url_param() method.  Use it in the same
way as param().  The main difference is that it allows you to
read the parameters, but not set them.
Under no circumstances will the contents of the URL query string interfere with similarly-named CGI parameters in POSTed forms. If you try to mix a URL query string with a form submitted with the GET method, the results will not be what you expect.
   $field = $query->radio_group(-name=>'OS',
                                -values=>[Unix,Windows,Macintosh],
                                -default=>'Unix');
The advantages of this style are that you don't have to remember the
exact order of the arguments, and if you leave out a parameter, it
will usually default to some reasonable value.  If you provide
a parameter that the method doesn't recognize, it will usually do
something useful with it, such as incorporating it into the HTML
tag as an attribute.  For example if Netscape decides next week to add a new
JUSTIFICATION parameter to the text field tags, you can start using
the feature without waiting for a new version of CGI.pm:
   $field = $query->textfield(-name=>'State',
                              -default=>'gaseous',
                              -justification=>'RIGHT');
This will result in an HTML tag that looks like this:
   <INPUT TYPE="textfield" NAME="State" VALUE="gaseous"
          JUSTIFICATION="RIGHT">
Parameter names are case insensitive: you can use -name, or -Name or
-NAME.
Actually, CGI.pm only looks for a hyphen in the first parameter.  So
you can leave it off subsequent parameters if you like.  Something to
be wary of is the potential that a string constant like "values" will
collide with a keyword (and in fact it does!) While Perl usually
figures out when you're referring to a function and when you're
referring to a string, you probably should put quotation marks around
all string constants just to play it safe.
HTML/HTTP parameters that contain internal hyphens, such as -Content-language can be passed by putting quotes around them, or by using an underscore for the second hyphen, e.g. -Content_language.
The fact that you must use curly {} braces around the attributes passed to functions that create simple HTML tags but don't use them around the arguments passed to all other functions has many people, including myself, confused. As of 2.37b7, the syntax is extended to allow you to use curly braces for all function calls:
   $field = $query->radio_group({-name=>'OS',
                                -values=>[Unix,Windows,Macintosh],
                                -default=>'Unix'});
Table of contents
   print $query->header('image/gif');
This prints out the required HTTP Content-type: header and the requisite
blank line beneath it.  If no parameter is specified, it will default to
'text/html'.
An extended form of this method allows you to specify a status code and a message to pass back to the browser:
   print $query->header(-type=>'image/gif',
                        -status=>'204 No Response');
This presents the browser with a status code of 204 (No response).
Properly-behaved browsers will take no action, simply remaining 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 when a user clicks on an empty part of a clickable image map.)
Several other named parameters are recognized. Here's a contrived example that uses them all:
   print $query->header(-type=>'image/gif',
                        -status=>'402 Payment Required',
                        -expires=>'+3d',
                        -cookie=>$my_cookie,
                        -charset=>'UTF-7',
                        -attachment=>'foo.gif',
                        -Cost=>'$0.02');
	+30s                              30 seconds from now
	+10m                              ten minutes from now
	+1h	                          one hour from now
        -1d                               yesterday (i.e. "ASAP!")
	now                               immediately
	+3M                               in three months
        +10y                              in ten years time
	Thu, 25-Apr-1999 00:40:33 GMT     at the indicated time & date
When you use -expires, the script also generates a
correct time stamp for the generated document to ensure that your
clock and the browser's clock agree.  This allows you to create
documents that are reliably cached for short periods of time.
CGI::expires() is the static function call used internally that turns relative time intervals into HTTP dates. You can call it directly if you wish.
print $query->header(-nph=>1,
                        -status=>'200 OK',
                        -type=>'text/html');
In either case, the outgoing header will be formatted as:print header(-p3p=>[qw(CAO DSP LAW CURa)]); print header(-p3p=>'CAO DSP LAW CURa');
P3P: policyref="/w3c/p3p.xml" cp="CAO DSP LAW CURa"
Cost: $0.02You can use this to take advantage of new HTTP header fields without waiting for the next release of CGI.pm.
   print $query->redirect('http://somewhere.else/in/the/world');
This generates a redirection request for the remote browser.  It will
immediately go to the indicated URL.  You should exit soon after this.
Nothing else will be displayed.
You can add your own headers to this as in the header() method.
You should always use full URLs (including the http: or ftp: part) in redirection requests. Relative URLs will not work correctly.
An alternative syntax for redirect() is:
print $query->redirect(-location=>'http://somewhere.else/',
                          -nph=>1,
                          -status=>301);
The -nph parameter, if non-zero tells CGI.pm that this script is running as a no-parsed-header script. See Using NPH Scripts for more information.
The -status parameter will set the status of the redirect. HTTP defines three different possible redirection status codes:
301 Moved Permanently 302 Found 303 See Other
The default if not specified is 302, which means "moved temporarily." You may change the status to another status code if you wish. Be advised that changing the status to anything other than 301, 302 or 303 will probably break redirection.
The -method parameter tells the browser what method to use for redirection. This is handy if, for example, your script was called from a fill-out form POST operation, but you want to redirect the browser to a static page that requires a GET.
All other parameters recognized by the header() method are also valid in redirect. Table of contents
   named parameter style
   print $query->start_html(-title=>'Secrets of the Pyramids',
                            -author=>'fred@capricorn.org',
                            -base=>'true',
			    -meta=>{'keywords'=>'pharoah secret mummy',
                                    'copyright'=>'copyright 1996 King Tut'},
			    -style=>{'src'=>'/styles/style1.css'},
                            -dtd=>1,
                            -BGCOLOR=>'blue');
   old style
   print $query->start_html('Secrets of the Pyramids',
                            'fred@capricorn.org','true');
This will return a canned HTML header and the opening <BODY> tag.  
All parameters are optional:
      print $query->start_html(-title=>'Secrets of the Pyramids',
                               -xbase=>'http://www.nile.eg/pyramid.html');
      
  
      print $query->start_html(-title=>'Secrets of the Pyramids',
                               -target=>'answer_frame');
      
      -target can be used with either
      -xbase or -base.
  
      <META NAME="keywords" CONTENT="pharoah secret mummy">
      <META NAME="description" CONTENT="copyright 1996 King Tut">
      
    print $q->start_html(-lang=>'fr-CA');
-dtd=>'-//W3C//DTD HTML 3.2//EN'
      print start_html(-head=>Link({-rel=>'next',
                       -href=>'http://www.capricorn.com/s2.html'}));
      
      or even
      
      print start_html(-head=>[ Link({-rel=>'next',
			                 -href=>'http://www.capricorn.com/s2.html'}),
			           Link({-rel=>'previous',
				         -href=>'http://www.capricorn.com/s1.html'})
			      ]
		      );
      
      To create an HTTP-EQUIV tag, use something like this:
      
      print start_html(-head=>meta({-http_equiv=>'Content-Type',
                                       -content=>'text/html'}))
      
  
      $query = new CGI;
      print $query->header;
      
      $JSCRIPT=<<END;
      // Ask a silly question
      function riddle_me_this() {
         var r = prompt("What walks on four legs in the morning, " +
                       "two legs in the afternoon, " +
                       "and three legs in the evening?");
         response(r);
      }
      // Get a silly answer
      function response(answer) {
         if (answer == "man")
            alert("Right you are!");
         else
            alert("Wrong!  Guess again.");
      }
      END
      
      print $query->start_html(-title=>'The Riddle of the Sphinx',
                               -script=>$JSCRIPT);
      
      Netscape 3.0 and higher allows you to place the JavaScript code
      in an external
      document and refer to it by URL.  This allows you to keep the JavaScript
      code in a file or CGI script rather than cluttering up each page with the
      source.  Netscape 3.X-4.X and Internet Explorer 3.X-4.X also recognize a "language"
      parameter that allows you to use other languages, such as VBScript and
      PerlScript (yes indeed!)  To use these attributes pass a HASH
      reference in the -script parameter containing one
      or more of the keys language, src, or
      code.  Here's how to refer to an external script URL:
      
      print $q->start_html(-title=>'The Riddle of the Sphinx',
			   -script=>{-language=>'JavaScript',
                                   -src=>'/javascript/sphinx.js'}
                              );
     
     Here's how to refer to scripting code incorporated directly into the page:
     
     print $q->start_html(-title=>'The Riddle of the Sphinx',
                          -script=>{-language=>'PerlScript',
                                    -code=>'print "hello world!\n;"'}
                             );
     
     A final feature allows you to incorporate multiple <SCRIPT> sections into the
     header.  Just pass the list of script sections as an array reference.
     This allows you to specify different source files for different dialects
     of JavaScript.  Example:     
     
     print $q->start_html(-title=>'The Riddle of the Sphinx',
                          -script=>[
                                    { -language => 'JavaScript1.0',
                                      -src      => '/javascript/utilities10.js'
                                    },
                                    { -language => 'JavaScript1.1',
                                      -src      => '/javascript/utilities11.js'
                                    },
                                    { -language => 'JavaScript1.2',
                                      -src      => '/javascript/utilities12.js'
                                    },
                                    { -language => 'JavaScript28.2',
                                      -src      => '/javascript/utilities219.js'
                                    }
                                 ]
                             );
     
    (If this looks a bit extreme, take my advice and stick with straight CGI scripting.)  
      print $query->start_html(-title=>'The Riddle of the Sphinx',
                                  -script=>$JSCRIPT,
                                  -onLoad=>'riddle_me_this()');
      
      See JavaScripting for more details.
  print $query->end_htmlThis ends an HTML document by printing the </BODY> </HTML> tags.
To see the list of HTML tags that are supported, open up the CGI.pm file and look at the functions defined in the %EXPORT_TAGS array.
print $query->hr;This prints out the text "<hr>".
   print $query->em("What a silly art exhibit!");
This prints out the text "<em>What a silly art
exhibit!</em>".
You can pass as many text arguments as you like: they'll be concatenated together with spaces. This allows you to create nested tags easily:
   print $query->h3("The",$query->em("silly"),"art exhibit");
This creates the text:
<h3>The <em>silly</em> art exhibit</h3>
When used in conjunction with the import facility, the HTML shortcuts can make CGI scripts easier to read. For example:
   use CGI qw/:standard/;
   print h1("Road Guide"),
         ol(
          li(a({href=>"start.html"},"The beginning")),
          li(a({href=>"middle.html"},"The middle")),
          li(a({href=>"end.html"},"The end"))
         );
Most HTML tags are represented as lowercase function calls. There are a few exceptions:
tr().  Use
      TR() or Tr() instead.
  param()  method.  Use
      PARAM() instead.
  Select() instead.
  Sub() instead.
   use CGI qw/:standard/;
   print a({-href=>"bad_art.html"},"Jump to the silly exhibit");
   <A HREF="bad_art.html">Jump to the silly exhibit</A>
You may dispense with the dashes in front of the attribute names if
you prefer:
   print img {src=>'fred.gif',align=>'LEFT'};
   <IMG ALIGN="LEFT" SRC="fred.gif">
Sometimes an HTML tag attribute has no argument.  For example, ordered
lists can be marked as COMPACT, or you wish to specify that a table
has a border with <TABLE BORDER>.  The syntax for this is an
argument that that points to an undef string:
   print ol({compact=>undef},li('one'),li('two'),li('three'));
Prior to CGI.pm version 2.41, providing an empty ('') string as an
attribute argument was the same as providing undef.  However, this has
changed in order to accomodate those who want to create tags of the form 
<IMG ALT="">.  The difference is shown in this table:
| CODE | RESULT | 
|---|---|
| img({alt=>undef}) | <IMG ALT> | 
| img({alt=>''}) | <IMT ALT=""> | 
print ul(
        li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']);
      );
You can take advantage of this to create HTML tables easily and naturally. Here is some code and the HTML it outputs:<UL> <LI TYPE="disc">Sneezy</LI> <LI TYPE="disc">Doc</LI> <LI TYPE="disc">Sleepy</LI> <LI TYPE="disc">Happy</LI> </UL>
use CGI qw/:standard :html3/;
print table({-border=>undef},
        caption(strong('When Should You Eat Your Vegetables?')),
        Tr({-align=>CENTER,-valign=>TOP},
        [
           th(['','Breakfast','Lunch','Dinner']),
           th('Tomatoes').td(['no','yes','yes']),
           th('Broccoli').td(['no','no','yes']),
           th('Onions').td(['yes','yes','yes'])
        ]
      )
);
| Breakfast | Lunch | Dinner | |
|---|---|---|---|
| Tomatoes | no | yes | yes | 
| Broccoli | no | no | yes | 
| Onions | yes | yes | yes | 
If you want to produce tables programatically, you can do it this way:
use CGI qw/:standard :html3/;
@values = (1..5);
@headings = ('N','N'.sup('2'),'N'.sup('3'));
@rows = th(\@headings);
foreach $n (@values) {
   push(@rows,td([$n,$n**2,$n**3]));
}
print table({-border=>undef,-width=>'25%'},
            caption(b('Wow.  I can multiply!')),
            Tr(\@rows)
           );
| N | N2 | N3 | 
|---|---|---|
| 1 | 1 | 1 | 
| 2 | 4 | 8 | 
| 3 | 9 | 27 | 
| 4 | 16 | 64 | 
| 5 | 25 | 125 | 
General note 2. The default values that you specify for the forms are only used the first time the script is invoked. If there are already values 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, you have two choices:
       print $query->textfield(-name=>'favorite_color',
                               -default=>'red',
			       -override=>1);
       
General note 4. By popular demand, the text and labels that 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 may interfere with your ability to incorporate special HTML
character sequences, such as Á (Á) into your fields.  If
you wish to turn off automatic escaping, call the autoEscape()
method with a false value immediately after creating the CGI object:
     $query = new CGI;
     $query->autoEscape(0);
You can turn autoescaping back on at any time with $query->autoEscape(1)
General note 5. Some of the form-element generating methods return multiple tags. In a scalar context, the tags will be concatenated together with spaces, or whatever is the current value of the $" global. In a list context, the methods will return a list of elements, allowing you to modify them if you wish. Usually you will not notice this behavior, but beware of this:
    printf("%s\n",$query->end_form())
end_form() produces several tags, and only the first of them will be
printed because the format only expects one value.
print $query->isindex($action);isindex() without any arguments returns an <ISINDEX> tag that designates your script as the URL to call. If you want the browser to call a different URL to handle the search, pass isindex() the URL you want to be called.
   print $query->startform($method,$action,$encoding);
     ...various form stuff...
   print $query->endform;
startform() will return a <FORM> tag with the
optional method, action and form encoding that you specify.
endform() returns a </FORM> tag.
The form encoding supports the "file upload" feature of Netscape 2.0 (and higher) and Internet Explorer 4.0 (and higher). The form encoding tells the browser how to package up the contents of the form in order to transmit it across the Internet. There are two types of encoding that you can specify:
$CGI::URL_ENCODED.
  CGI::MULTIPART()
       Forms that use this type of encoding are not easily interpreted by CGI scripts unless they use CGI.pm or another library that knows how to handle them. Unless you are using the file upload feature, there's no particular reason to use this type of encoding.
startform().
If you plan to make use of the JavaScript
features, you can provide startform() with the
optional -name and/or -onSubmit parameters.
-name has no effect on the display of the form, but can
be used to give the form an identifier so that it can be manipulated
by JavaScript functions.  Provide the -onSubmit parameter
in order to register some JavaScript code to be performed just before
the form is submitted.  This is useful for checking the validity of a
form before submitting it.  Your JavaScript code should return a value
of "true" to let Netscape know that it can go ahead and submit the
form, and "false" to abort the submission.
   print $query->start_multipart_form($method,$action,$encoding);
     ...various form stuff...
   print $query->endform;
This has exactly the same usage as startform(), but
it specifies form encoding type multipart/form-data
as the default.
  Named parameter style
  print $query->textfield(-name=>'field_name',
	                    -default=>'starting value',
	                    -size=>50,
	                    -maxlength=>80);
   Old style
  print $query->textfield('foo','starting value',50,80);
textfield() will return a text input field.
When the form is processed, the value of the text field can be retrieved with:
      $value = $query->param('foo');
JavaScripting: You can also provide -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut and -onSelect parameters to register JavaScript event handlers.
   Named parameter style
   print $query->textarea(-name=>'foo',
	 		  -default=>'starting value',
	                  -rows=>10,
	                  -columns=>50);
   Old style
   print $query->textarea('foo','starting value',10,50);
textarea() is just like textfield(), but it allows 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.
JavaScripting: Like textfield(), you can provide -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut and -onSelect parameters to register JavaScript event handlers.
   Named parameter style
   print $query->password_field(-name=>'secret',
				-value=>'starting value',
				-size=>50,
				-maxlength=>80);
   Old style
   print $query->password_field('secret','starting value',50,80);
password_field() is identical to textfield(), except that its contents 
will be starred out on the web page.
    Named parameters style
    print $query->filefield(-name=>'uploaded_file',
	                    -default=>'starting value',
	                    -size=>50,
	 		    -maxlength=>80);
    Old style
    print $query->filefield('uploaded_file','starting value',50,80);
filefield() will return a form field that prompts the user
to upload a file.
In order to take full advantage of the file upload
facility you must use the new multipart
form encoding scheme.  You can do this either
by calling startform()
and specify an encoding type of $CGI::MULTIPART
or by using the new start_multipart_form()
method.  If you don't use multipart encoding, then you'll be
able to retrieve the name of the file selected by the remote
user, but you won't be able to access its contents.
When the form is processed, you can retrieve the entered filename by calling param().
       $filename = $query->param('uploaded_file');
where "uploaded_file" is whatever you named the file upload field.
Depending on the browser version, the filename that gets returned may
be the full local file path on the remote user's
machine, or just the bare filename.  If a path is provided, the
follows the path conventions of the local machine.
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;
        }
       close $filename;
There are problems with the dual nature of the upload fields.  If you
use strict, then Perl will complain when you try to use a
string as a filehandle.  You can get around this by placing the file
reading code in a block containing the no strict pragma.
More seriously, it is possible for the remote user to type garbage
into the upload field, in which case what you get from param()
is not a filehandle at all, but a string.
To be safe, use the upload() function (new in version 2.47). When called with the name of an upload field, upload() returns a filehandle, or undef if the parameter is not a valid filehandle.
     $fh = $query->upload('uploaded_file');
     while (<$fh>) {
	   print;
     }
In an list context, upload() will return an array of filehandles. This makes it possible to create forms that use the same name for multiple upload fields.
This is the recommended idiom.
You can have several file upload fields in the same form, and even
give them the same name if you like (in the latter case
param() will return a list of file names).  However, if
the user attempts to upload several files with exactly the same name,
CGI.pm will only return the last of them.  This is a known bug.
When processing an uploaded file, CGI.pm creates a temporary file on your hard disk and passes you a file handle to that file. After you are finished with the file handle, CGI.pm unlinks (deletes) the temporary file. If you need to you can access the temporary file directly. Its name is stored inside the CGI object's "private" data, and you can access it by passing the file name to the tmpFileName() method:
       $filename = $query->param('uploaded_file');
       $tmpfilename = $query->tmpFileName($filename);
The temporary file will be deleted automatically when your program exits unless you manually rename it. On some operating systems (such as Windows NT), you will need to close the temporary file's filehandle before your program exits. Otherwise the attempt to delete the temporary file will fail.
You can set up a callback that will be called whenever a file upload is being read during the form processing. This is much like the UPLOAD_HOOK facility available in Apache::Request, with the exception that the first argument to the callback is an Apache::Upload object, here it's the remote filename.
 $q = CGI->new(\&hook);
 sub hook  {
        my ($filename, $buffer, $bytes_read, $data) = @_;
        print  "Read $bytes_read bytes of $filename\n";         
 }
If using the function-oriented interface, call the CGI::upload_hook() method before calling param() or any other CGI functions: CGI::upload_hook(\&hook,$data);
This method is not exported by default. You will have to import it explicitly if you wish to use it without the CGI:: prefix.
A potential problem with the temporary file upload feature is that the temporary file is accessible to any local user on the system. In previous versions of this module, the temporary file was world readable, meaning that anyone could peak at what was being uploaded. As of version 2.36, the modes on the temp file have been changed to read/write by owner only. Only the Web server and its CGI scripts can access the temp file. Unfortunately this means that one CGI script can spy on another! To make the temporary files really private, set the CGI global variable $CGI::PRIVATE_TEMPFILES to 1. Alternatively, call the built-in function CGI::private_tempfiles(1), or just use CGI qw/-private_tempfiles. The temp file will now be unlinked as soon as it is created, making it inaccessible to other users. The downside of this is that you will be unable to access this temporary file directly (tmpFileName() will continue to return a string, but you will find no file at that location.) Further, since PRIVATE_TEMPFILES is a global variable, its setting will affect all instances of CGI.pm if you are running mod_perl. You can work around this limitation by declaring $CGI::PRIVATE_TEMPFILES as a local at the top of your script.
On Windows NT, it is impossible to make a temporary file private. This is because Windows doesn't allow you to delete a file before closing it.
Usually the browser sends along some header information along with the text of the file itself. Currently the headers contain only the original file name and the MIME content type (if known). Future browsers might 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. For example, this code fragment retrieves the MIME type of the uploaded file (be careful to use the proper capitalization for "Content-Type"!):
       $filename = $query->param('uploaded_file');
       $type = $query->uploadInfo($filename)->{'Content-Type'};
       unless ($type eq 'text/html') {
	  die "HTML FILES ONLY!";
       }
JavaScripting: Like textfield(), filefield() accepts -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut and -onSelect parameters to register JavaScript event handlers. Caveats and potential problems in the file upload feature.
  Named parameter style
  print $query->popup_menu(-name=>'menu_name',
                            -values=>[qw/eenie meenie minie/], 
			    -labels=>{'eenie'=>'one',
                                         'meenie'=>'two',
                                         'minie'=>'three'},
	                    -default=>'meenie');
  print $query->popup_menu(-name=>'menu_name',
			    -values=>['eenie','meenie','minie'],
	                    -default=>'meenie');
  
  Old style
  print $query->popup_menu('menu_name',
                              ['eenie','meenie','minie'],'meenie',
                              {'eenie'=>'one','meenie'=>'two','minie'=>'three'});
popup_menu() creates a menu.
     $popup_menu_value = $query->param('menu_name');
JavaScripting: You can provide -onChange,
-onFocus, -onMouseOver, -onMouseOut, and -onBlur parameters
to register JavaScript event handlers.
   Named parameter style
   print $query->scrolling_list(-name=>'list_name',
                                -values=>['eenie','meenie','minie','moe'],
                                -default=>['eenie','moe'],
	                        -size=>5,
	                        -multiple=>'true',
                                -labels=>\%labels);
   Old style
   print $query->scrolling_list('list_name',
                                ['eenie','meenie','minie','moe'],
                                ['eenie','moe'],5,'true',
                                \%labels);
scrolling_list() creates a scrolling list.
%labels
       has already been created.  
     @selected = $query->param('list_name');
JavaScripting: You can provide -onChange,
-onFocus, -onMouseOver, -onMouseOut and
-onBlur parameters to register JavaScript event handlers.
   Named parameter style
   print $query->checkbox_group(-name=>'group_name',
                                -values=>['eenie','meenie','minie','moe'],
                                -default=>['eenie','moe'],
	                        -linebreak=>'true',
	                        -labels=>\%labels);
   Old Style
   print $query->checkbox_group('group_name',
                                ['eenie','meenie','minie','moe'],
                                ['eenie','moe'],'true',\%labels);
   HTML3 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.
%labels
       has previously been created.  This is equivalent to passing a
      hash reference to -values. If you don't use
      -nolabels, CGI.pm will add HTML label
      tag around each checkbox and its label, so a browser can identify the
      text as form element label properly.
 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 interpetation of the checkboxes -- they're still a single named unit.
When viewed with browsers that don't understand HTML3 tables, the -rows and -columns parameters will leave you with a group of buttons that may be awkwardly formatted but still useable. However, if you add row and/or column headings, the resulting text will be very hard to read.
     @turned_on = $query->param('group_name');
This function actually returns an array of button elements.  You can
capture the array and do interesting things with it, such as incorporating
it into your own tables or lists.  The -nolabels option
is also useful in this regard:
       @h = $query->checkbox_group(-name=>'choice',
                                    -value=>['fee','fie','foe'],
                                    -nolabels=>1);
       create_nice_table(@h);
JavaScripting: You can provide an -onClick
parameter to register some JavaScript
code to be performed every time the user clicks on any of the buttons
in the group.
   Named parameter list
   print $query->checkbox(-name=>'checkbox_name',
			   -checked=>'checked',
		           -value=>'TURNED ON',
		           -label=>'Turn me on');
   Old style
   print $query->checkbox('checkbox_name',1,'TURNED ON','Turn me on');
checkbox() is used to create an isolated checkbox that isn't logically
related to any others.
     $turned_on = $query->param('checkbox_name');
JavaScripting: You can provide an -onClick
parameter to register some JavaScript
code to be performed every time the user clicks on the button.
   Named parameter style
   print $query->radio_group(-name=>'group_name',
			     -values=>['eenie','meenie','minie'],
                             -default=>'meenie',
			     -linebreak=>'true',
			     -labels=>\%labels);
   Old style
   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.
\@foo.  You may also use a hash reference in
      order to produce human-readable labels that are different from
      the values that will be returned as parameters to the CGI
      script.
  %labels has already been defined.  This is
      equivalent to passing a hash reference to -values.
      If you don't use -nolabels, CGI.pm will add HTML label
      tag around each radio button and its label, so a browser can identify the
      text as form element label properly.
  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 viewed with browsers that don't understand HTML3 tables, the -rows and -columns parameters will leave you with a group of buttons that may be awkwardly formatted but still useable. However, if you add row and/or column headings, the resulting text will be very hard to read.
       $which_radio_button = $query->param('group_name');
This function actually returns an array of button elements.  You can
capture the array and do interesting things with it, such as incorporating
it into your own tables or lists  The -nolabels option
is useful in this regard.:
       @h = $query->radio_group(-name=>'choice',
                                 -value=>['fee','fie','foe'],
                                 -nolabels=>1);
       create_nice_table(@h);
JavaScripting: You can provide an -onClick parameter to register some JavaScript code to be performed every time the user clicks on any of the buttons in the group.
   Named parameter style
   print $query->submit(-name=>'button_name',
		        -value=>'value');
  Old style
  print $query->submit('button_name','value');
submit() will create the query submission button.  Every form
    should have one of these.
You can figure out which of several buttons was pressed by using different values for each one:
    $which_one = $query->param('button_name');
  -name and -value changes the user-visible
      label on the button.
print $query->resetreset() creates the "reset" button. It undoes whatever changes the user has recently made to the form, but does not necessarily reset the form all the way to the defaults. See defaults() for that. It takes the optional label for the button ("Reset" by default). JavaScripting: You can provide an -onClick parameter to register some JavaScript code to be performed every time the user clicks on the button.
  print $query->defaults('button_label')
defaults() creates "reset to defaults" button.
It takes the optional label for the button ("Defaults" by default).
When the user presses this button, the form will automagically
be cleared entirely and set to the defaults you specify in your
script, just as it was the first time it was called.
   Named parameter style
   print $query->hidden(-name=>'hidden_name',
                        -default=>['value1','value2'...]);
   Old style
   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.
Hidden fields used to behave differently from all other fields: the provided default values always overrode the "sticky" values. This was the behavior people seemed to expect, however it turns out to make it harder to write state-maintaining forms such as shopping cart programs. Therefore I have made the behavior consistent with other fields.
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 before writing out the form element:
     $query->param('hidden_name','new','values','here');
     print $query->hidden('hidden_name');
Fetch the value of a hidden field this way:
    $hidden_value = $query->param('hidden_name');
            -or (for values created with arrays)-
    @hidden_values = $query->param('hidden_name');
   Named parameter style
   print $query->image_button(-name=>'button_name',
                              -src=>'/images/NYNY.gif',
                              -align=>'MIDDLE');	
   Old style
   print $query->image_button('button_name','/source/URL','MIDDLE');
image_button() 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.
    $x = $query->param('button_name.x');
    $y = $query->param('button_name.y');
JavaScripting: Current versions of JavaScript do not
honor the -onClick handler, unlike other buttons.
   Named parameter style
   print $query->button(-name=>'button1',
                           -value=>'Click Me',
                           -onClick=>'doButton(this)');	
   Old style
   print $query->image_button('button1','Click Me','doButton(this)');
button() creates a JavaScript button.  When the button is
pressed, the JavaScript code pointed to by the -onClick parameter
is executed.  This only works with Netscape 2.0 and higher.  Other browsers
do not recognize JavaScript and probably won't even display the button.
autoEscape().
Use
    $query->autoEscape(0);
to turn automatic HTML escaping off, and
    $query->autoEscape(1);
to turn it back on.
This imports the standard methods into your namespace. Now instead of getting parameters like this:use CGI qw(:standard);
use CGI;
$dinner = $query->param('entree');
use CGI qw(:standard);
$dinner = param('entree');
print $query->start_form,
      "Check here if you're happy: ",
      $query->checkbox(-name=>'happy',-value=>'Y',-checked=>1),
      "<P>",
      $query->submit,
      $query->end_form;
print start_form,
      "Check here if you're happy: ",
      checkbox(-name=>'happy',-value=>'Y',-checked=>1),
      p,
      submit,
      end_form;
$CGI::Q;
The use CGI statement is used to import method names into the current name space. There is a slight overhead for each name you import, but ordinarily is nothing to worry about. You can import selected method names like this:
Ordinarily, however, you'll want to import groups of methods using export tags. Export tags refer to sets of logically related methods which are imported as a group with use. Tags are distinguished from ordinary methods by beginning with a ":" character. This example imports the methods dealing with the CGI protocol (use CGI qw(header start_html end_html);
param() and the like) as well as shortcuts that generate
HTML2-compliant tags:
Currently there are 8 method families defined in CGI.pm. They are:use CGI qw(:cgi :html2);
      use CGI qw(-any);
      $q=new CGI;
      print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});
      
      use CGI qw(-compile :standard :html3);
      
      use CGI qw(-compile :all);
      Note that using the -compile pragma in this way will always have the effect of importing the compiled functions into the current namespace. If you want to compile without importing use the compile() method instead.
      
      $href = $q->self_url();
      $href = escapeHTML($href);
      print I'm talking to myself
      
      
      
      
      name=fred;age=24;favorite_color=3
      
      
      As of version 2.64, this is the default style.
  
      use CGI qw(-no_debug :standard);
      
See debugging for more details.
  print h1('Level 1 Header');
produces
<H1>Level 1 Header</H1>There will be some times when you want to produce the start and end tags yourself. In this case, you can use the form start_Itag_name and end_Itag_name, as in:
print start_h1,'Level 1 Header',end_h1;With a few exceptions (described below), start_tag_name and end_Itag_name functions are not generated automatically when you use CGI. However, you can specify the tags you want to generate start/end functions for by putting an asterisk in front of their name, or, alternatively, requesting either "start_tag_name" or "end_tag_name" in the import list.
Example:
use CGI qw/:standard *table start_ul/;In this example, the following functions are generated in addition to the standard ones:
start_table() (generates a <TABLE> tag)
  end_table() (generates a </TABLE> tag)
  start_ul() (generates a <UL> tag)
  end_ul() (generates a </UL> tag)
$escaped_string = escapeHTML("unescaped string");
Provided that you have specified a character set of ISO-8859-1 (the default), the standard HTML escaping rules will be used. The "<" character becomes "<", ">" becomes ">", "&" becomes "&", and the quote character becomes """. In addition, the hexadecimal 0x8b and 0x9b characters, which many windows-based browsers interpret as the left and right angle-bracket characters, are replaced by their numeric HTML entities ("‹" and "›"). If you manually change the charset, either by calling the charset() method explicitly or by passing a -charset argument to header(), then all characters will be replaced by their numeric entities, since CGI.pm has no lookup table for all the possible encodings.
Autoescaping does not apply to other HTML-generating functions, such as h1(). You should call escapeHTML() yourself on any data that is passed in from the outside, such as nasty text that people may enter into guestbooks.
To change the character set, use charset(). To turn autoescaping off completely, use autoescape():
$charset = charset([$charset]); # Get or set the current character set. $flag = autoEscape([$flag]); # Get or set the value of the autoescape flag.
use CGI qw/escape unescape/;
$q = escape('This $string contains ~wonderful~ characters');
$u = unescape($q);
use CGI qw/escapeHTML unescapeHTML/;
$q = escapeHTML('This string is <illegal> html!');
$u = unescapeHTML($q);
use CGI ();
CGI->compile(':all');
my_script.pl keyword1 keyword2 keyword3or this:
my_script.pl keyword1+keyword2+keyword3or this:
my_script.pl name1=value1 name2=value2or this:
my_script.pl name1=value1&name2=value2If you pass the -debug pragma to CGI.pm, you can send CGI name-value pairs as newline-delimited parameters on standard input:
% my_script.pl first_name=fred last_name=flintstone occupation='granite miner' ^D
When debugging, you can use quotation marks and the backslash character to escape spaces and other funny characters in exactly the way you would in the shell (which isn't surprising since CGI.pm uses "shellwords.pl" internally). This lets you do this sort of thing:
    my_script.pl 'name 1=I am a long value' name\ 2=two\ words
If you run a script that uses CGI.pm from the command line and fail to provide it with any arguments, it will print out the line
(offline mode: enter name=value pairs on standard input)then appear to hang. In fact, the library is waiting for you to give it some parameters to process on its standard input. If you want to give it some parameters, enter them as shown above, then indicate that you're finished with input by pressing ^D (^Z on NT/DOS systems). If you don't want to give CGI.pm parameters, just press ^D.
You can suppress this behavior in any of the following ways:
      my_script.pl ''
      
      
      my_script.pl </dev/null
      
      
      use CGI qw/:standard -no_debug/;
      
print $query->DumpProduces something that looks like this:
   <UL>
   <LI>name1
       <UL>
       <LI>value1
       <LI>value2
       </UL>
   <LI>name2
       <UL>
       <LI>value1
       </UL>
   </UL>
You can achieve the same effect by incorporating the CGI object directly
into a string, as in:
print "<H2>Current Contents:</H2>\n$query\n";
$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.  Note the capitalization of the initial letter.  This avoids
      conflict with the Perl built-in accept().
  /cgi-bin/your_script/additional/stuff will
       result in $query->path_info() returning
       "/additional/stuff".  In addition to reading the
      path information, you can set it by giving path_info() an
      optional string argument.  The argument is expected to begin
      with a "/".  If not present, one will be added for you.  The new
      path information will be returned by subsequent calls to
      path_info(), and will be incorporated into the URL generated by
      self_url().
  "/usr/local/etc/httpd/htdocs/additional/stuff".
      You cannot change the path_translated, nor will setting the
      additional path information change this value.  The reason for
      this restriction is that the translation of path information
      into a physical path is ordinarily done by the server in a layer
      that is inaccessible to CGI scripts.
  GET, POST, or HEAD.
  For example, all three of these examples are equivalent:
   $requested_language = $q->http('Accept-language');
   $requested_language = $q->http('Accept_language');
   $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE');
  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:
Negative expiration times (e.g. "-1d") cause some browsers to delete the cookie from its persistent store. This is a poorly documented feature.
    $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
      
  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('answers');
	# $query->cookie(-name=>'answers') works too!
To retrieve the names of all cookies passed to your script, call
cookie() without any parameters.  This allows you to
iterate through all cookies:
	foreach $name ($query->cookie()) {
            print $query->cookie($name);
        }
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 are some limitations on cookies. Here is what RFC2109, section 6.3, states:
   Practical user agent implementations have limits on the number and
   size of cookies that they can store.  In general, user agents' cookie
   support should have no fixed limits.  They should strive to store as
   many frequently-used cookies as possible.  Furthermore, general-use
   user agents should provide each of the following minimum capabilities
   individually, although not necessarily simultaneously:
      * at least 300 cookies
      * at least 4096 bytes per cookie (as measured by the size of the
        characters that comprise the cookie non-terminal in the syntax
        description of the Set-Cookie header)
      * at least 20 cookies per unique host or domain name
   User agents created for specific purposes or for limited-capacity
   devices should provide at least 20 cookies of 4096 bytes, to ensure
   that the user can interact with a session-based origin server.
   The information in a Set-Cookie response header must be retained in
   its entirety.  If for some reason there is inadequate space to store
   the cookie, it must be discarded, not truncated.
   Applications should use as few and as small cookies as possible, and
   they should cope gracefully with the loss of a cookie.
Unfortunately, some browsers appear to have limits that are more
restrictive than those given in the RFC.  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.
-target
      parameter.  When the form is submitted, the output
      will be redirected to the indicated frame:
      
      print $query->start_form(-target=>'result_frame');
      
  -target argument in the header method.  For example,
      the following code will pop up a new window and display the script's
      output:
      
      $query = new CGI;
      print $query->header(-target=>'_blank');
      
      This feature is a non-standard extension to HTTP which is supported
      by Netscape browsers, but not by Internet Explorer.
The examples directory contains a script called popup.cgi that demonstrates a simple popup window. frameset.cgi provides a skeleton script for creating side-by-side query/result frame sets.
You'll need to know JavaScript in order to use it. The Netscape JavaScript manual contains a good tutorial and reference guide to the JavaScript programming language.
The usual way to use JavaScript is to define a set of functions in a <SCRIPT> block inside the HTML header and then to register event handlers in the various elements of the page. Events include such things as the mouse passing over a form element, a button being clicked, the contents of a text field changing, or a form being submitted. When an event occurs that involves an element that has registered an event handler, its associated JavaScript code gets called.
The elements that can register event handlers include the <BODY> of an HTML document, hypertext links, all the various elements of a fill-out form, and the form itself. There are a large number of events, and each applies only to the elements for which it is relevant. Here is a partial list:
validateAge() JavaScript code executed every time the
textfield named "age" changes, generate the field like this:
print $q->textfield(-name=>'age',-onChange=>"validateAge(this)");This example assumes that you've already declared the
validateAge() function by incorporating it into
a <SCRIPT> block.  The CGI.pm
start_html() method provides a convenient way
to create this section.
Similarly, you can create a form that checks itself over for consistency and alerts the user if some essential value is missing by creating it this way:
print $q->startform(-onSubmit=>"validateMe(this)");See the javascript.cgi script for a demonstration of how this all works.
The JavaScript "standard" is still evolving, which means that new handlers may be added in the future, or may be present in some browsers and not in others. You do not need to wait for a new version of CGI.pm to use new event handlers. Just like any other tag attribute they will produce syntactically correct HTML. For instance, if Microsoft invents a new event handler called onInterplanetaryDisaster, you can install a handler for it with:
print button(-name=>'bail out',-onInterPlaneteryDisaster=>"alert('uh oh')");
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 MIME type of the stylesheet by including an optional -type parameter in the hash pointed to by -style. If not specified, the type 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');
print h1({-style=>'Color: red;'},'Welcome to Hell');
print span({-style=>'Color: red;'},
	       h1('Welcome to Hell'),
	       "Where did that handbasket get to?"
          );
You won't be able to do much with this unless you understand the CSS specification. A more intuitive subclassable library for cascading style sheets in Perl is in the works, but until then, please read the CSS specification at http://www.w3.org/pub/WWW/Style/ to find out how to use these features. Here's a final example to get you started.
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;
Pass an array reference to -code or -srcin order to incorporate multiple stylesheets into your document.
Should you wish to incorporate a verbatim stylesheet that includes arbitrary formatting in the header, you may pass a -verbatim tag to the -style hash, as follows:
print $q->start_html (-STYLE => {-verbatim => '@import url("/server-common/css/'.$cssFile.'");', -src => '/server-common/css/core.css'});
This will generate HTML like this:
<link rel="stylesheet" type="text/css" href="/server-common/css/core.css"> <style type="text/css"> @import url("/server-common/css/main.css"); </style>
Any additional arguments passed in the -style value will be incorporated into the <link> tag. For example:
This will give:start_html(-style=>{-src=>['/styles/print.css','/styles/layout.css'], -media => 'all'});
<link rel="stylesheet" type="text/css" href="/styles/print.css" media="all"/> <link rel="stylesheet" type="text/css" href="/styles/layout.css" media="all"/>
To make more complicated <link> tags, use the Link() function and pass it to start_html() in the -head argument, as in:
  @h = (Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/ss.css',-media=>'all'}),
        Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/fred.css',-media=>'paper'}));
  print start_html({-head=>\@h})
Servers use a variety of conventions for designating CGI scripts as NPH. IIS and many Unix servers look at the beginning of the script's name for the prefix "nph-".
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.
Important: If you use the Microsoft Internet Information Server, you must designate your script as an NPH script. Otherwise many of CGI.pm's features, such as redirection and the ability to output non-HTML files, will fail. However, after applying Service Pack 6, NPH scripts do not work at all on IIS without a special patch from Microsoft. See Knowledgebase article Q280/3/31 Non-Parsed Headers Stripped From CGI Applications That Have nph- Prefix in Name
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);
      
#!/usr/local/bin/perl
use CGI;
$query = new CGI;
print $query->header;
print $query->start_html("Save and Restore Example");
print "<H1>Save and Restore Example</H1>\n";
# Here's where we take action on the previous request
&save_parameters($query)              if $query->param('action') eq 'save';
$query = &restore_parameters($query)  if $query->param('action') eq 'restore';
# Here's where we create the form
print $query->startform;
print "Popup 1: ",$query->popup_menu('popup1',['eenie','meenie','minie']),"\n";
print "Popup 2: ",$query->popup_menu('popup2',['et','lux','perpetua']),"\n";
print "<P>";
print "Save/restore state from file: ",$query->textfield('savefile','state.sav'),"\n";
print "<P>";
print $query->submit('action','save'),$query->submit('action','restore');
print $query->submit('action','usual query');
print $query->endform;
# Here we print out a bit at the end
print $query->end_html;
sub save_parameters {
    local($query) = @_;
    local($filename) = &clean_name($query->param('savefile'));
    if (open(FILE,">$filename")) {
	$query->save(\*FILE);
	close FILE;
	print "<STRONG>State has been saved to file $filename</STRONG>\n";
    } else {
	print "<STRONG>Error:</STRONG> couldn't write to file $filename: $!\n";
    }
}
sub restore_parameters {
    local($query) = @_;
    local($filename) = &clean_name($query->param('savefile'));
    if (open(FILE,$filename)) {
	$query = new CGI(\*FILE);  # Throw out the old query, replace it with a new one
	close FILE;
	print "<STRONG>State has been restored from file $filename</STRONG>\n";
    } else {
	print "<STRONG>Error:</STRONG> couldn't restore file $filename: $!\n";
    }
    return $query;
}
# Very important subroutine -- get rid of all the naughty
# metacharacters from the file name. If there are, we
# complain bitterly and die.
sub clean_name {
   local($name) = @_;
   unless ($name=~/^[\w\._-]+$/) {
      print "<STRONG>$name has naughty characters.  Only ";
      print "alphanumerics are allowed.  You can't use absolute names.</STRONG>";
      die "Attempt to use naughty characters";
   }
   return $name;
}
If you use the CGI save() and restore() methods a lot, you might be
interested in the Boulderio
file format.  It's a way of transferring semi-strucured data from the
standard output of one program to the standard input of the next.  It
comes with a simple Perl database that allows you to store and
retrieve records from a DBM or DB_File database, and is compatible
with the format used by save() and restore().  You can get more
information on Boulderio from:
http://stein.cshl.org/software/boulder/
Many people have experienced problems with internal links on pages that have forms. Jumping around within the document causes the state of the form to be reset. A partial solution is to use the self_url() method to generate a link that preserves state information. This script illustrates how this works.
#!/usr/local/bin/perl
use CGI;
$query = new CGI;
# We generate a regular HTML file containing a very long list
# and a popup menu that does nothing except to show that we
# don't lose the state information.
print $query->header;
print $query->start_html("Internal Links Example");
print "<H1>Internal Links Example</H1>\n";
print "<A NAME=\"start\"></A>\n"; # an anchor point at the top
# pick a default starting value;
$query->param('amenu','FOO1') unless $query->param('amenu');
print $query->startform;
print $query->popup_menu('amenu',[('FOO1'..'FOO9')]);
print $query->submit,$query->endform;
# We create a long boring list for the purposes of illustration.
$myself = $query->self_url;
print "<OL>\n";
for (1..100) {
    print qq{<LI>List item #$_<A HREF="$myself#start">Jump to top</A>\n};
}
print "</OL>\n";
print $query->end_html;
There is, however, a problem with maintaining the states of multiple forms. Because the browser only sends your script the parameters from the form in which the submit button was pressed, the state of all the other forms will be lost. One way to get around this, suggested in this example, is to use hidden fields to pass as much information as possible regardless of which form the user submits.
#!/usr/local/bin/perl
use CGI;
$query=new CGI;
print $query->header;
print $query->start_html('Multiple forms');
print "<H1>Multiple forms</H1>\n";
# form 1
print "<HR>\n";
print $query->startform;
print $query->textfield('text1'),$query->submit('submit1');
print $query->hidden('text2');  # pass information from the other form
print $query->endform;
print "<HR>\n";
# form 2
print $query->startform;
print $query->textfield('text2'),$query->submit('submit2');
print $query->hidden('text1');  # pass information from the other form
print $query->endform;
print "<HR>\n";
print $query->end_html;
If you use standard subclassing techniques and restrict yourself to using CGI.pm and its subclasses in the object-oriented manner, you'll have no problems. However, if you wish to use the function-oriented calls with your subclass, follow this model:
package MySubclass;
use vars qw(@ISA $VERSION);
require CGI;
@ISA = qw(CGI);
$VERSION = 1.0;
$CGI::DefaultClass = __PACKAGE__;
$AutoloadClass = 'CGI';
sub new {
   ....
}
1;
The second trick is to set the package variable $AutoloadClass to the string "CGI". This tells the CGI autoloader where to look for functions that are not defined. If you wish to override CGI's autoloader, set this to the name of your own package.
More information on extending CGI.pm can be found in my new book, The Official Guide to CGI.pm, which was published by John Wiley & Sons in April 1998. Check out the book's Web site, which contains multiple useful coding examples.
FastCGI modules are available for the Apache and NCSA servers as well as for OpenMarket's own server. In order to use FastCGI with Perl you have to run a specially-modified version of the Perl interpreter. Precompiled Binaries and a patch kit are all available on OpenMarket's FastCGI web site.
To use FastCGI with CGI.pm, change your scripts as follows:
#!/usr/local/bin/perl
use CGI qw(:standard);
print header,
      start_html("CGI Script"),
      h1("CGI Script"),
      "Not much to see here",
      hr,
      address(a({href=>'/'},"home page"),  
      end_html;
#!/usr/local/fcgi/bin/perl
use CGI::Fast qw(:standard);
# Do time-consuming initialization up here.
while (new CGI::Fast) {
   print header,
      start_html("CGI Script"),
      h1("CGI Script"),
      "Not much to see here",
      hr,
      address(a({href=>'/'},"home page"),  
      end_html;
}
#!/usr/local/bin/perl
use CGI qw(:standard);
print header,
      start_html("CGI Script"),
      h1("CGI Script"),
      "Not much to see here",
      hr,
      address(a({href=>'/'},"home page"),  
      end_html;
#!/usr/bin/perl
use CGI::Apache qw(:standard);
print header,
    start_html("CGI Script"),
    h1("CGI Script"),
    "Not much to see here",
    hr,
    address(a({href=>'/'},"home page"),  
    end_html;
}
mod_perl comes with a small wrapper library named CGI::Switch that selects dynamically between using CGI and CGI::Apache. This library is no longer needed. However users of CGI::Switch can continue to use it without risk. Note that the "simple" interface to the CGI.pm functions does not work with CGI::Switch. You'll have to use the object-oriented versions (or use the sfio version of Perl!)
If you use CGI.pm in many of your mod_perl scripts, you may want to preload CGI.pm and its methods at server startup time. To do this, add the following line to httpd.conf:
Create the file /home/httpd/conf/startup.pl and put in it all the modules you want to load. Include CGI.pm among them and call its compile() method to precompile its autoloaded methods.PerlScript /home/httpd/conf/startup.pl
#!/usr/local/bin/perl
use CGI ();
CGI->compile(':all');
When you call ReadParse(), CGI.pm creates an associative array named
%in that contains the named CGI parameters.  Multi-valued
parameters are separated by "\0" characters in exactly the same way
cgi-lib.pl does it.  The function result is the number of parameters
parsed.  You can use this to determine whether the script is being
called from a fill out form or not.
To port an old script to CGI.pm, you have to make just two changes:
    require "cgi-lib.pl";
    ReadParse();
    print "The price of your purchase is $in{price}.\n";
    use CGI qw(:cgi-lib);
    ReadParse();
    print "The price of your purchase is $in{price}.\n";
Like cgi-lib's ReadParse, pass a variable glob in
order to use a different variable than the default "%in":
   ReadParse(*Q);
   @partners = split("\0",$Q{'golf_partners'});
The associative array created by CGI::ReadParse() contains a special key 'CGI', which returns the CGI query object itself:
    ReadParse();
    $q = $in{CGI};
    print $q->textfield(-name=>'wow',
                        -value=>'does this really work?');
This allows you to add the more interesting features
of CGI.pm to your old scripts without rewriting them completely.
As an added benefit, the %in variable is
actually tie()'d to the CGI object.  Changing the
CGI object using param() will dynamically
change %in, and vice-versa.
cgi-lib.pl's @in and $in variables are
not supported.  In addition, the extended version of
ReadParse() that allows you to spool uploaded files to disk is not
available.  You are strongly encouraged to use CGI.pm's file upload
interface instead.
See cgi-lib_porting.html for more details on porting cgi-lib.pl scripts to CGI.pm.
Known problems include:
      $file = $query->param('file to upload');
      $file = "main::$file";
          ...
      /usr/tmp or the /tmp
directory.  These temporary files
have names like CGItemp125421, and should be
deleted automatically.
    first_name=Fred
    last_name=Flintstone
    city=Bedrock
End the list by typing a control-D (or control-Z on DOS/Windows
systems).
If you want to run a CGI script from a script or batch file, and don't want this behavior, just pass it an empty parameter list like this:
     my_script.pl ''
This will work too on Unix systems:
     my_script.pl </dev/null
Another option is to use the "-no_debug" pragma when you "use"
CGI.pm.  This will suppress command-line debugging completely:
use CGI qw/:standard -no_debug/;
Due to problems that integer.pm has with unary negation, calls to CGI.pm that use the -arg=>value format will break if you load the integer.pm module. This is fixed in Perl 5.005_61 and up.
A workaround is to put all arguments in quotes: '-arg'=>'value'
CGITemp123456 in a temporary
directory.  To find a suitable directory it first looks
for /usr/tmp and then for /tmp.
If it can't find either of these directories, it tries
for the current directory, which is usually the same
directory that the script resides in.  
If you're on a non-Unix system you may need to modify CGI.pm to point at a suitable temporary directory. This directory must be writable by the user ID under which the server runs (usually "nobody") and must have sufficient capacity to handle large file uploads. Open up CGI.pm, and find the line:
      package TempFile;
      foreach ('/usr/tmp','/tmp') {
         do {$TMPDIRECTORY = $_; last} if -d $_ && -w _;
      }
Modify the foreach() line to contain a series of one or more
directories to store temporary files in.
Alternatively, you can just skip the search entirely and force CGI.pm to store its temporary files in some logical location. Do this at the top of your script with a line like this one: $TempFile::TMPDIRECTORY='/WWW_ROOT';
\temp, taking up space.Unix users don't have this problem, because well designed operating systems make it possible to delete a file without closing it.
A workaround for this is to use additional path information to trick Netscape into thinking that the form and the response have different URLs. I recommend giving each form a sequence number and bumping the sequence up by one each time the form is accessed:
my($s) = $query->path_info=~/(\d+)/; # get sequence $s++; #bump it up # Trick Netscape into thinking it's loading a new script: print $q->start_multipart_form(-action=>$q->script_name . "/$s");
CGI.pm provides four simple functions for producing multipart documents of the type needed to implement server push. 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!');
foreach (0 .. 4) {
   print multipart_start(-type=>'text/plain'),
         "The current time is ",scalar(localtime),"\n";
   if ($_ < 4) {
      print multipart_end;
   } else {
      print multipart_final;
   }
   sleep 1;
}
This script initializes server push by calling multipart_init(). It then enters a 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. On the final iteration, it ends the multipart section with multipart_final() rather than with multipart_end().
multipart_init(-boundary=>$boundary);
      
multipart_start(-type=>$type)
      
  multipart_end()
      
  multipart_final()
      Only Netscape Navigator supports server push. Internet Explorer browsers do not.
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:
      use CGI qw/:standard/;
      use CGI::Carp 'fatalsToBrowser';
      $CGI::POST_MAX=1024 * 100;  # max 100K posts
      $CGI::DISABLE_UPLOADS = 1;  # no uploads
      
      
An attempt to send a POST larger than $POST_MAX bytes will cause param() to return an empty CGI parameter list. You can test for this event by checking cgi_error(), either after you create the CGI object or, if you are using the function-oriented interface, call param() for the first time. If the POST was intercepted, then cgi_error() will return the message "413 POST too large".
This error message is actually defined by the HTTP protocol, and is designed to be returned to the browser as the CGI script's status code. For example:
$uploaded_file = param('upload');
   if (!$uploaded_file && cgi_error()) {
      print header(-status=>cgi_error());
      exit 0;
   }
Some browsers may not know what to do with this status code. It may be better just to create an HTML page that warns the user of the problem. Table of contents
There are a number of differences in file name and text processing conventions on different platforms. By default, CGI.pm is set up to work properly on a Unix (or Linux) system. During load, it will attempt to guess the correct operating system using the Config module. Currently it guesses correctly; however if the operating system names change it may not work right. The main symptom will be that file upload does not work correctly. If this happens, find the place at the top of the script where the OS is defined, and uncomment the correct definition:
# CHANGE THIS VARIABLE FOR YOUR OPERATING SYSTEM # $OS = 'UNIX'; # $OS = 'MACINTOSH'; # $OS = 'WINDOWS'; # $OS = 'VMS';Other notes follow:
.pl suffix
with perl5 using the NT file manager (Website, Purveyor), or install
the correct script mapping registry keys for IIS.  Perl for Windows is
available from the ActiveState company, which can be found at:
http://www.activestate.com/
WebSite uses a slightly different cgi-bin directory structure than
the standard.  For this server, place the scripts in the
cgi-shl directory.  CGI.pm appears to work correctly
in both the Windows95 and WindowsNT versions of WebSite.
Old Netscape Communications Server technical notes recommended
placing perl.exe in cgi-bin.  This a very bad idea because
it opens up a gaping security hole.  Put a C .exe wrapper
around the perl script until such time as Netscape recognizes NT file
manager associations, or provides a Perl-compatible DLL library for its
servers.
If you find that binary files get slightly larger when uploaded but that text files remain the same, then binary made is not correctly activated. Be sure to set the $OS variable to 'NT' or 'WINDOWS'. If you continue to have problems, make sure you're calling binmode() on the filehandle that you use to write the uploaded file to disk.
Known incompatibilities between CGI.pm and MacPerl include:ftp://err.ethz.ch/pub/neeri/MacPerl/
The CGI::* modules are being reworked to be interoperable with the excellent LWP modules. Stay tuned.
The current version of CGI.pm can be found at:
http://www.genome.wi.mit.edu/ftp/pub/software/WWW/
You are encouraged to look at these other Web-related modules:
For a collection of CGI scripts of various levels of complexity, see the companion pages for my book How to Set Up and Maintain a World Wide Web Site
http://www.wiley.com/compbooks/stein/
perl -MCGI -e 'print $CGI::VERSION')
  perl -v)
  September 13, 2000
September 12, 2000
August 19, 2000
August 13, 2000
August 4, 2000
      <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
      
  user_name() and remote_user()
       methods.
  autoEscape() method.
v  Last modified: Thu Nov 2 09:20:02 EST 2006