Vol. 1, No. 40
CGI Modules, Part Two
Welcome to this week's installment of Handcrafted, the only Tripod
newsletter with Pneumodyne, the secret ingredient guaranteed not to
promote tooth decay--now with 60 percent more Pneumodyne!
Okay now. Onward we plunge, deeper and deeper into the mysterious,
exciting world of CGI modules. To reiterate, Tripod provides these
little pluggable modules that incorporate common functions, making
it easier than you can imagine to write CGI scripts. And CGI scripts
are what you need; they make the difference between brochureware
sites and huge e-business portals. Last issue, as you recall, after
lavishing praise on Tripod for providing these fantastic modules,
we learned how to install and use the modules, and then took a close
look at a couple of them. If you were distracted for some reason,
you can refresh your memory by glancing at the last newsletter: Using the CGI Modules Tripod Gives You
This week we are going to meet a couple more of our new friends.
TripodPage is a module that automates a lot of the tedious parts
of making dynamic pages: that is, pages that display different
content at different times or for different users. (A classic example
of this is the lying "new content" footer--that little line of text
at the bottom of the page that says "Last Updated: [today's date]"
on that site you haven't touched in months. TripodPage gives you
the power: the consequences of lying to your visitors is your own
lookout.)
As usual, we invoke the module with a snippet of Perl code that looks
like this:
require TripodPage;
$PAGE = new TripodPage;
The essential function that TripodPage offers is sendPage(). It sends an
HTML page to a user, interpolating the current values of any variables
it's told to. The arguments it takes are the location of the HTML file
and the variables. The way it works is simple, but it takes a little
space to explain, so bear with it.
Let's say we want to make a page that displays the page visitor's IP
address. First we create the basic HTML template, which can be as simple
as:
<HTML>
Hi. Your IP address is $ipaddress.
</HTML>
Save that file as address.html. (Please pardon us if the example pages
aren't as snazzy as they could be.)
Next we write our CGI script to plug the actual IP address info into
that page. We get the info itself from the hash of CGI environment
variables, which will be explained very soon. The script looks like
this:
require TripodPage;
$PAGE = new TripodPage;
$outputpage = 'address.html';
$ourhash{ipaddress} = $ENV{REMOTE_ADDR};
$PAGE->sendPage($outputpage, \%ourhash);
exit;
Then, when someone visits the page, they will be pleasantly surprised to
see something like:
Hi. Your IP address is 192.168.0.63.
or whatever, depending on what their actual IP address is.
Hashes and Environment Variables
A hash, also known as an associative array, is a type of array variable
where the index is a string. So, in the example above, the name of the
hash is ourhash, and the index we use is ipaddress. How it works is not
important to know, but it's worth mentioning, as we meet a hash in this
code. When referring to a hash in its entirety we prefix its name with a
% sign. (Just like a scalar is prefixed with a $ and an array with a @.)
TripodPage likes to be fed a hash, even if (as in the above example) the
hash just contains a single value.
Anyway. The exciting part is where we grab the user's IP address from
the CGI environment. There are a number of juicy tidbits like that
floating around in the CGI environment, and they're all easily
accessible -- Perl receives them as elements of the hash %ENV. So we
have, for example, $ENV(REMOTE_ADDR), $ENV(HTTP_REFERER),
$ENV(CONTENT_LENGTH), and suchlike. (Are you still stuck back on hashes?
When you refer to a hash AS A WHOLE, its name is prefixed with a %.
When, like we're doing here, you refer to just a single element of the
hash, you prefix the hash's name with a $, and identify the element you
want by its index in parentheses. All right?)
REMOTE_ADDR, as we saw in our example, contains the IP address of the
user. HTTP_REFERER (note: that's REFERER, not REFERRER, no matter what
your elementary school teacher may have told you) contains the URL of
the page that the user came to your page from. HTTP_USER_AGENT is a fun
one -- it tells what browser your visitor is using. Also good are
SCRIPT_NAME, which gives the path of the script that's running, and
SERVER_NAME, which contains the name of the server. And of course
QUERY_STRING is indispensable: this contains the string of variables (if
any) that are passed to the script -- that is to say, everything in the
URL after the question mark (if such exists).
Well, that was a bit of a digression. Back to TripodPage. If you want to
include more than one variable in your page, just add another element to
the hash. So to modify the above example to display the browser type as
well, we would just add the line
$ourhash{browsertype} = $ENV{HTTP_USER_AGENT};
to the script, and the line
<P>And your browser is $browsertype.
to the HTML page. Simple enough.
So that's how to use sendPage(). Another function, sendNonCachedPage(),
is very similar in function, but the pages it sends include header
information specifying to the browser that they should expire instantly
and not be cached.
That's the gist of what TripodPage does: simple, but powerful. Another
module, TripodInsert, works along similar lines. TripodInsert is useful
when your dynamic page is going to change significantly from hit to hit
-- when you want not just a few variables, but the majority of the
content of the page, to be different each time. The key function
TripodInsert offers is fetchInsert(). Here is how it's used:
require TripodInsert;
$INSERT = new TripodInsert;
$templatepage = 'address.html';
$ourhash{ipaddress} = $ENV{REMOTE_ADDR};
$ourhash{browsertype} = $ENV{HTTP_USER_AGENT};
$newpage = $INSERT->fetchInsert($outputpage, \%ourhash);
This works just like old sendPage(), except instead of sending the new
page containing the variable data to the user's browser, at this point
it just stores it in the variable $newpage. We can do whatever we want
with that variable: send it to the user, save it as a permanent file on
the server -- whatever. fetchInsert() can be useful for logging user
data -- just create a log template file and write each user's variables
to it using the fetchInsert() function.
There's not too much more to it than that. These functions have a very
general application -- what they do is basic and very flexible, so you
can use them again and again to accomplish all sorts of different coding
tasks. They aren't the only tools you'll ever need, but they are
incredibly handy.
HINTS, POINTERS, AND TIPS 'O THE TRADE:
You can invoke as many Perl modules as you want in each script, just by
tacking on more "require" statements. But each one has a memory overhead
which slows down the execution process, so it's best to just call on the
ones you need. But sometimes when you're writing a script from scratch,
you may want to require them all at the beginning, just to give yourself
some elbow room, and then, once the script is working, eliminate the
calls you don't need.
You can look at how the Tripod Perl modules work by going to your
cgi-bin directory in the file manager and opening the module files.
Refrigerating bread tends to make it stale. Freezing it is okay, though.
RESOURCES:
CGI environment variables
Explanation of Perl data types
Write your own CGI scripts
Intro to CGI
Webmonkey's guide to CGI
Webmonkey: CGI Scripts for Fun and Profit