# # GBasic.pl - Basic Perl Routines to deal with the HTTP protocol # # Originally written by Steven E. Brenner (S.E.Brenner@bioc.cam.ac.uk) and # modified/hacked by Clint Goss (clint@goss.com) December 1995 and # November 1998. # package GBasic; # Perl Modules use strict; # Restrict unsafe variables, references, barewords # ReadParse # # Reads in GET or POST data, converts it to unescaped text, and puts # one key=value in each member of the list "@in". Also creates key/value # pairs in %in, using '\0' to separate multiple selections. # # Returns TRUE if there was input, FALSE if there was no input. # Now that cgi scripts can be put in the normal file space, it is useful # to combine both the form and the script in one place. If no parameters # are given (i.e., ReadParse returns FALSE), then a form could be output. sub ReadParse { my ($in); # Read in the text, depending on the method if (&MethGet) { $in = $ENV{'QUERY_STRING'}; } elsif (&MethPost) { read (STDIN, $in, $ENV{'CONTENT_LENGTH'}); } my (@in) = split (/[&;]/, $in); my ($i, %in); foreach $i (0 .. $#in) { # Split into key and value - splits on the first =. my ($key, $val) = split (/=/, $in[$i], 2); # Convert embedded '+' characters and any embedded %XX # hex numbers to their corresponding characters. # Also save the undecoded values, for anyone who is interested $key =~ tr/+/ /; $key =~ s/%(..)/pack ("c", hex ($1))/ge; $val =~ tr/+/ /; $val =~ s/%(..)/pack ("c", hex ($1))/ge; # Associate key and value # \0 is the multiple separator $in{$key} .= "\0" if (defined ($in{$key})); $in{$key} .= $val; } return %in; } # X/YCoordinate (@in) # Fetch the x and y coordinates for a hit on a clickable image sub XCoordinate { my ($in) = $ENV{'QUERY_STRING'}; my (@in) = split (/[&;]/, $in); return (split (/,/, $in[0], 2)) [0]; } sub YCoordinate { my ($in) = $ENV{'QUERY_STRING'}; my (@in) = split (/[&;]/, $in); return (split (/,/, $in[0], 2)) [1]; } # MethGet, MethPost # Return true if this cgi call was using the GET request method or # POST request method (respectively), undef otherwise sub MethGet { return ($ENV{'REQUEST_METHOD'} eq "GET"); } sub MethPost { return ($ENV{'REQUEST_METHOD'} eq "POST"); } # MyURL # Returns a URL to the script sub MyURL { my ($port) = ":" . $ENV{'SERVER_PORT'} if $ENV{'SERVER_PORT'} != 80; return 'http://' . $ENV{'SERVER_NAME'} . $port . $ENV{'SCRIPT_NAME'}; } # CgiError # Prints out an error message which which containes appropriate headers, # markup, etcetera. # # Parameters: If no parameters, gives a generic error message. # Otherwise, the first parameter will be the title and the rest will # be given as different paragraphs of the body. sub CgiError { my (@msg) = @_; if (!@msg) { my ($name) = &MyURL; @msg = ("Error: script $name encountered a fatal error"); } print "Content-type: text/html\n\n"; print "
$msg[$i]
\n"; } # Just in case we were in a table or two, close them so that # our text is shown. print "\n", "\n", "\n", "\n"; } # dieCgi # Identical to CgiError, but also quits with the passed error message. sub dieCgi { my (@msg) = @_; &CgiError (@msg); die @msg; } # For the remainder of this library: # original author: Mohamed Hendawi (moe@pobox.com) # updates/hacks by: Clint Goss (clint@goss.com) # # BrowserFeatureAvailable # # Given a browser string as per the environment variable HTTP_USER_AGENT # and a feature: # # return 0 for not available # return 1 for available # return 2 for don't recognize feature string # # Current supported features are in the table below. # sub browserFeatureAvailable { my ($browser, $feature) = @_; # MULTIPART-X-MIXED-REPLACE - supports Content-type: multipart/x-mixed-replace my (%features) = ( 'MULTIPART-X-MIXED-REPLACE' => ["Mozilla", "!MSIE"], 'FRAMES' => ["Mozilla/[23456789].*"], "MSIE" ); if (!defined ($features{$feature})) { # Er, ah, which feature was that you wanted?? return 2; } # Here if we know about the feature being queried my ($regexp); my ($avail) = 0; foreach $regexp (@{$features{$feature}}) { if ($regexp =~ m/^\!/) { $regexp = substr ($regexp, 1); if (eval ("\$browser =~ m|$regexp|i;")) { return 0; } } else { if (eval ("\$browser =~ m|$regexp|i;")) { $avail = 1; } } } return $avail; } 1; #return true __END__ =head1 NAME GBasic.pl - Simplified CGI interface routines =head1 SYNOPSIS # Access to modules (see the NOTES section for setup) BEGIN { ... push (@INC, ...location of your library directory...); } require 'GBasic.pl'; # Read any data from the requesting form and then # pick up the parameters for this script (from form # data or specified on the URL). my (%in) = &GBasic::ReadParse; # Fetch the CGI parameter "FIELD". my ($fieldValue) = $in{"FIELD"}; =head1 DESCRIPTION This Perl5 library implements a perl interface to the HTTP Common Gateway Interface (CGI) protocol. It is similar to the popular cgi-lib.pl, but with some simplifications: - The rarely used and cantankerous Mime/Multipart protocol is not supported. =head2 Functions =over 4 =item %in = ReadParse () Reads in GET or POST data, converts it to text (removing HTTP %xx escape sequences), and puts one key=value in each member of the %in hash. Duplicate GET or POST parameters (typically generated from lists which allow multiple selections) have a single entry in the %in hash with the individual values separated by '\0'. =item XCoordinate () =item YCoordinate () Returns the X and Y coordinates for a hit on a clickable image. =item MethGet () Return true if this cgi call was using the GET request, false otherwise. =item MethPost () Return true if this cgi call was using the POST request, false otherwise. =item MyURL () Returns a URL which invoked the CGI script. =item CgiError (@msg) Prints out an error message which which contains appropriate headers, HTML markup, etcetera. If no parameters are supplied, CgiError displays a generic error message. Otherwise, the first parameter will be the title and the rest will be displayed as different paragraphs of the body of the generated HTML page. =item dieCgi (@msg) Identical to CgiError(), but also issues a perl die() with the supplied error message. =item browserFeatureAvailable ($browser, $feature) Given a browser string as per the environment variable HTTP_USER_AGENT and a feature: return 0 for not available return 1 for available return 2 for don't recognize feature string Current supported features are: 'MULTIPART-X-MIXED-REPLACE' 'FRAMES' =back =head1 WARNING None =head1 SEE ALSO G(3) =head1 NOTES This module has not yet been set up for "installation" in your local Perl. =head1 AUTHOR Clint Goss