here's the CGI library that supports the previous script.
one thing i forgot to mention.. you have to name the file 'CGI.pm' for the
perl interpreter to know how to find it.
---- CGI.pm ----
#### SUPPORT PACKAGE: CGI ROUTINES ####
package CGI;
###
#
# this function allocates storage for the global data used in the
# other functions. the main reason for abstracting a bunch of
# assignments into a separate function is to make the functions
# which use the values more readable.
#
sub _init_globals {
$HEADER = "Content-type: text/html\n\n";
@ERR_METHOD = (
"Method",
"The input method",
qq("$main::ENV{'REQUEST_METHOD'}"),
"is not supported by this script."
);
}
###
#
# this function sets up a lookup table which maps x-encoded
# character codes to the corresponding ASCII characters. at the
# moment, it only maps the standard printing characters to the
# correct values.. anything else is mapped to a space.
#
sub _init_LUT {
for $i (0..255) {
$s = sprintf ("%02x", $i);
$LUT{"\L$s"} = " ";
}
$sp = unpack 'c', ' ';
$z = unpack 'c', 'z';
for $i ($sp..$z) {
$s = sprintf ("%02x", $i);
$LUT{"\L$s"} = pack "C", $i;
}
$LUT_READY = 1;
}
###
#
# this function takes a string of x-encoded data as input and uses
# the lookup table (configured above) to turn it into straight
# ASCII.
#
sub clean {
my $data = shift;
if ( ! $LUT_READY ) {
&_init_LUT;
}
$data =~ s/\+/ /g;
my @parts = $data =~ /%(..)/g;
my %uniq = map (($_,1), @parts);
for $item (keys %uniq) {
$data =~ s/%$item/$LUT{"\L$item"}/ig;
}
return ($data);
}
###
#
# this function checks the request method to make sure it matches
# the script's preference. this isn't as flexible as reading any
# input whatsoever, but it's more disciplined.
#
sub ck_method {
my $method = shift;
if ($main::ENV{'REQUEST_METHOD'} ne $method) {
&error (@ERR_METHOD);
}
}
###
#
# this function takes a string of x-encoded data as its input, and
# returns a reference to a hash of decoded name/value pairs.
#
# for a given key, the hash actually contains a reference to an
# anonymous list, which in turn contains the data. it's a bit
# memory-intensive, but i don't expect to see large numbers of
# variables, and it's a more effective way to store things.
#
sub parse_input {
my $data = shift;
%HASH = ();
if ( ! $LUT_READY ) {
&_init_LUT;
}
my @pairs = split (/&/, $data);
for $item (@pairs) {
my ($name, $val) = split (/=/, $item);
$name = &clean ($name);
$val = &clean ($val);
my $key = $HASH{ $name };
if (ref $key) {
push @{ $key }, $val;
} else {
my $ref = [];
$ref->[0] = $val;
$HASH{ $name } = $ref;
}
}
}
###
#
# this is the main input routine. it reads standard input and
# parses what it finds into the appropriate data structures.
#
sub read_stdin {
&ck_method ('POST');
$RAW_INPUT = "";
read (STDIN, $RAW_INPUT, $main::ENV{'CONTENT_LENGTH'});
&parse_input ($RAW_INPUT);
}
###
#
# this is the main input routine. it reads standard input and
# parses what it finds into the appropriate data structures.
#
sub read_query {
&ck_method ('GET');
$RAW_INPUT = $ENV{'QUERY_STRING'};
&parse_input ($RAW_INPUT);
}
###
#
# this is an accessor function. it's used in those cases where
# the main code needs the data direct from the httpd.
#
sub get_raw_input {
return $RAW_INPUT;
}
###
#
# this is an accessor function. it returns a list of all the
# variables passed from the form.
#
sub get_names {
return (sort keys %HASH);
}
###
#
# this is an accessor function. it takes a variable name as
# input and returns a list containing the associated value(s). it
# makes the way &parse_input() stores data in the hash transparent.
#
sub get_values {
my $name = shift;
my $val = $HASH{ $name };
if (ref $val) {
return (wantarray) ? @{ $val } : join (', ', @{ $val });
} else {
return 0;
}
}
###
#
# this is a debugging function which dumps the incoming data as a
# webpage, then quits.
#
sub echo {
print $HEADER;
for $item (&get_names) {
print "<br> $item = ", get_val ($item);
}
exit (1);
}
###
#
# this is an accessor function. it takes the name of a variable
# as input and returns (efffectively) a boolean which indicates
# whether the hash contains an entry by that name. it's intended
# for use with switching variables (i.e.: checkboxes), where the
# item's actual value is irrelevant.
#
sub is_def {
my $name = shift;
return ($HASH{ $name }) ? 1 : 0;
}
###
#
# this is a utility routine which prints an error page and
# terminates the program.
#
sub error {
my $type = shift;
my $message = join ("\n", @_);
print <<__done;
Content-type: text/html
<head><title>$type Error</title></head>
<body>
<h1>510 $type Error</h1>
$message
</body>
__done
exit (1);
}
###
#
# this is a utility function which redirects the browser to
# another file.
#
sub redirect_to {
my $url = shift;
print <<__done;
Location: $url
<head><title>redirection</title></head>
<body>
The page you requested has been moved <a href="$url">here.</a>
</body>
__done
}
1;
---- EOF ----
mike stone <[EMAIL PROTECTED]> 'net geek..
been there, done that, have network, will travel.