Porting cgi-lib.pl Scripts to CGI.pm
Steve Brenner, author of cgi-lib.pl, recently asked me to prepare a
document that compares cgi-lib.pl to CGI.pm and to give some advice for people
wishing to port scripts from one to the other.
I heartily endorse cgi-lib.pl for people who have good reasons for
sticking with Perl version 4. However, sites that use Perl 5.001 and
higher should seriously consider switching to CGI.pm or to the CGI::*
modules. Here are some reasons why.
Why use CGI.pm instead of cgi-lib.pl?
At their core, both cgi-lib.pl and CGI.pm provide convenient ways to
get at CGI query strings. There are a number of reasons to use CGI.pm
in preference to cgi-lib.pl.
- CGI.pm provides better support for multi-valued parameters.
- Named parameters that correspond to checkboxes and selection
lists are frequently multi-valued. With cgi-lib.pl, you must
manually split the components with split() or (in version 2.0)
with SplitParam():
@players=split("\0",$in{'players'});
With CGI.pm, you retrieve single or multi-valued parameters
with the same syntax:
@players=param('players');
- CGI.pm provides a more elegant interface to file uploads.
- In cgi-lib.pl you have to anticipate in advance how large
Netscape file uploads may be and select whether the file is to
be read into main memory or spooled to disk. CGI.pm
provides you with a variable that you can treat as a scalar to
recover the original file name, or as a file handle that you can
read from just as if you were reading the original file. You
don't have to worry about spooling issues:
$in_file = param('file_to_upload');
while (<$in_file>) {
$lineCount++;
}
- CGI.pm gives you lots of HTML and HTTP shortcuts.
- CGI.pm includes methods that generate HTTP headers,
redirection requests, and HTML tags (including
the Netscape extensions). These features are not included in
cgi-lib.pl
- CGI.pm provides a simple way of creating "sticky" forms and
maintaining state.
- Among the HTML tag-generating shortcuts are methods for
generating the elements of fill-out forms. By default, these
methods use the current query string to initialize the form
element contents. This gives you a simple mechanism for saving
the state of a session, and has the nice side effect that the
form doesn't revert back to its initial state every time you
regenerate it. Other methods in CGI.pm allow you to save
state in URLs, write the state out to a file, or even store the
session state in an external database.
- CGI.pm gives you access to advanced HTTP and HTML features.
- Support for persistent cookies, Netscape frames and JavaScript
is built into the module, along with some of the more esoteric
HTTP features such as content negotiation.
Reasons not to migrate to CGI.pm
The main difference is performance. On a Pentium 90 system running
Linux, cgi-lib.pl takes 0.11 seconds to load. CGI.pm takes 0.21
seconds. If that tenth of a second matters to you, then you should
continue to use cgi-lib.pl.
How do I migrate from cgi-lib.pl to CGI.pm?
A compatability mode allows you to port most scripts that use
cgi-lib.pl to CGI.pm without making extensive source code changes.
Most of the functions defined in cgi-lib.pl version 2.10 are available
for your use. Missing functions are easy to work around. Follow this
model:
Old Script
require "cgi-lib.pl";
&ReadParse;
print "The price of your purchase is $in{price}.\n";
New Script
use CGI qw(:cgi-lib);
&ReadParse;
print "The price of your purchase is $in{price}.\n";
In most cases the only change you'll need to make is the
require line. The line
use CGI qw(:cgi-lib);
instructs Perl to read in CGI.pm and to import into your script's name
space the cgi-lib.pl compatability routines. (In case you've never
run into this syntax before, the colon in front of
cgi-lib
indicates that we're importing a family of
routines identified by the tag cgi-lib rather than a
single routine.) The main routine that is imported is
ReadParse, which behaves in exactly the same way as
cgi-lib.pl's. You can call it without any parameters, in which case
it will place the query string in the associative array
%in
, or pass it the name of the associative array that
you want to use:
ReadParse(*Query);
@partners = split("\0",$Query{'golf_partners'});
CGI.pm is object-oriented, meaning that the parsed query string is
stored inside a "CGI" object. When you use ReadParse(), a default CGI
object is created: behind the scenes access to the %in
associative array is actually reading and writing its values to the
CGI object. You can get direct access to the underlying object by
using the special key 'CGI':
&ReadParse;
print "The price of your purchase is $in{price}.\n";
$q = $in{CGI};
print $q->textfield(-name=>'price',
-default=>'$1.99');
This allows you to start taking advantage of the CGI.pm features
without scouring your code for all the places where you used the
cgi-lib.pl %in
variable. An even simpler way to mix
cgi-lib calls with CGI.pm calls is to import both the
:cgi-lib and :standard method:
use CGI qw(:cgi-lib :standard);
&ReadParse;
print "The price of your purchase is $in{price}.\n";
print textfield(-name=>'price',
-default=>'$1.99');
Cgi-lib functions that are available in CGI.pm
In compatability mode, the following cgi-lib.pl functions are
available for your use:
- ReadParse()
- PrintHeader()
- HtmlTop()
- HtmlBot()
- SplitParam()
- MethGet()
- MethPost()
Cgi-lib functions that are not available in CGI.pm
- Extended form of ReadParse()
- The extended form of ReadParse() that provides for file upload
spooling, is not available. However you can read the contents
of the file directly from %in as follows:
print "The name of the file is $in{uploaded_file};
while (<$in{uploaded_file}>) {
print "Next line = $_";
}
- MyBaseURL()
- This function is not available. Use CGI.pm's url() method instead.
- MyFullURL()
- This function is not available. Use CGI.pm's self_url() method
instead.
- CgiError(), CgiDie()
- These functions are not supported. Look at CGI::Carp for the way I
prefer to handle error messages.
- PrintVariables()
- This function is not available. To achieve the same effect,
just print out the CGI object:
use CGI qw(:standard);
$q = new CGI;
print h1("The Variables Are"),$q;
- PrintEnv()
- This function is not available. You'll have to roll your own if
you really need it.
- @in not supported
- The original ReadParse() stores the individual elements of the
query string in an array named
@in
. This rarely-
used feature is not supported. To retrieve the keywords from an
oldstyle <ISINDEX> search, fetch the special array key
keywords:
@keywords = SplitParam($in{'keywords'});
Caveats
The compatability routines are a recent feature (added in CGI.pm
version 2.20, released on May 22, 1996) and may contain bugs.
Caveat emptor!
CGI.pm Documentation
Lincoln D. Stein, lstein@genome.wi.mit.edu
Whitehead Institute/MIT Center for Genome Research
Last modified: Wed May 22 23:33:25 EDT 1996