EIW Fall 2000 Lecture Notes - eiwcgi.pl
eiw-cgi.pl CGI library
We already looked at the GetQuery subroutine - we now look
at a few other subroutines that are useful for CGI programs.
http_header
Any CGI program that sends an HTML document back to the browser needs
to include an HTTP header indicating that the document is HTML. The CGI
should also send a blank line that marks the end of the HTTP header lines.
The following subroutine takes care of this and makes sure that the
header is sent only once.
# --------------------------------------------
# http header generation
# this subroutine should be called before the perl CGI program
# prints anything!
# The extra logic in this subroutine just makes sure that the
# header is never sent twice.
#
# example usage:
# http_header();
sub http_header {
if (! $http_header ) {
print "Content-type: text/html\n\n";
$http_header=1;
}
}
|
|
Handling Errors
CGI programs always need to make sure that the query includes all
the expected name/value pairs! Remember that just because you expect
that your CGI will only be accessed from forms (or links) you create,
you can't assume anything! Anyone can build a query by hand (or create
thier own form) and send all kinds of crazy stuff.
When an error occurs in a CGI program, the program will typically send
back an error message (formatted as an HTML document) and quit. The
following subroutine handles both tasks - first by sending back an
HTML document containing an error message and then by calling the perl
exit function. This subroutine also attempts to create
a back button so the user can easily return to the previous
web page. The back button depends on the server creating
an environment variable named "HTTP_REFERER" that contains
the URL of the refering page - this information is not always available
so the back button is only created if the environment variable
exists.
# --------------------------------------------
# fatal_error generates an HTML error message and quits.
# This subroutine should only be called when a fatal
# error condition occurs, something like the query didn't
# include expected fields.
# Any parameters to this subroutine are treated as strings that
# should be sent back as part of the error message.
#
# a back button is created that the user can press to go back to
# the refering page (typically the form that was sent here) if the
# environment variable REFERER is found (otherwise no back button
# is created).
#
# Example usage:
# fatal_error("You must fill in all fields in the form!\n");
sub fatal_error {
# send the HTTP header
http_header();
# and make this a real HTML document
print "<HEAD><TITLE>Error!</TITLE></HEAD>\n";
print "<BODY><HTML>\n";
# send a generic error message back to the browser
print "<H2>ERROR - YOUR QUERY COULD NOT BE PROCESSED</H2>\n";
local($line);
# now send back any parameters passed to this subroutine
print @_;
# now create the back button
local($referer) = $ENV{'HTTP_REFERER'};
if ($referer) {
print "<P>\n";
print "Press <A HREF=$referrer>here</A> to return\n";
}
# and close out the HTML document
print "</HTML></BODY>\n";
# terminate this program
exit;
}
|
|
It is important to check for all error conditions before sending any
document content back! You typically don't want to send back half of
an HTML document followed by an error document!
Sending a static file
Another common operation is to send back the contents of a file
containing part of an HTML document. This saves the programmer from
creating all parts of an HTML document using print statements. For
example, you could create a file that contains HTML that is always
sent at the top of every HTML document. The following subroutine reads
the contents of a named file and sends the file to the browser using
print commands:
# --------------------------------------------
#
# send_file will read in a file and send the contents of the
# file to the browser. This is useful when part of the HTML
# you want to generate is always the same - just put it in
# a file instead of coding it in print statements
#
# example usage:
# send_file("header.html");
sub send_file {
local($filename) = $_[0];
# attempt to open the file
if (! open(F,$filename) ) {
# Can't open the file - this is a fatal error!
fatal_error("Can't find the file $filename\n");
}
# the file is open - read everything and send to
# the browser
local(@lines) = <F>; # reads the whole file
print @lines; # sends all the lines to the browser
close(F); # close the file
}
|
|
Since it is possible that this subroutine can generate an error (if called
with a parameter that names a file that does not exist) it is possible that
the subroutine fatal_error can be called from within
send_file.
send_file looks for files in the "current directory", which
means the directory that holds the CGI program itself (assuming you use
the default configuration for the Xitami server).
Using eiw-cgi.pl
In perl you can store a collection of subroutines in a file and include
all the subroutines in your program using the require function.
For example, your CGI program might have the following in it:
#!/perl/bin/perl
#
# the following line is needed if we want to use any of the
# subroutines defined in the file "eiw-cgi.pl" which is a
# CGI library.
require "eiw-cgi.pl";
# This CGI program creates a table from the name/value pairs found in
# the query.
# get the name/value pairs in the assoc. array named %fields
%fields = GetQuery();
# Here is how to get the value of a field named "age":
$age = $fields{"age"};
|
|
The require statement looks for files in the current
directory (as well as some other places), so you probably need to put
a copy of eiw-cgi.pl in your CGI directory. The require command
evaluates each line of the named file (typically a sequence of subroutine
definitions - but it could be anything) and looks for a value of TRUE after
evaluating the last line in the file. If the last line of the file does not
have the perl value TRUE the require command reports a fatal error and
perl will quit! The simplest way to handle this is to always include the
following line as the last line in a file holding a bunch of perl subroutines:
# this last line is needed ! (the return value of this file is used
# by the "require" statement, and the return value is the last
# statement in the file).
1;
|
|