EIW Fall 2000 Lecture Notes - Perl/CGI


CGI libraries

In general, all CGI programs share a set of common operations: There are a couple of widely used libraries (perl modules or packages) that support these operations: You can use any perl library you want, the examples and lecture notes will use our own library to support CGI programming (based roughly on the cgi-lib library). Below we derive the functions included in "eiw-cgi.pl", the perl library we will use for the example CGI programs.

Building a CGI library for perl - eiw-cgi.pl

Our library will include the following functionality:

Reading the query string

Recall that the query can be provided via two mechanisms:
  1. METHOD=GET.   The query is in the environment variable named "QUERY_STRING".
  2. METHOD=POST.   The query is coming from STDIN and the length of the query string is contained in the environment variable "CONTENT-LENGTH".
To read an environment variable in perl, you can simply use the associative array named %ENV. The index for each member of the associative array is the environment variable name, so to get the value of the environment variable "REQUEST_METHOD" you can simply do this:
$method = $ENV{"REQUEST_METHOD"};
. We now know everything we need to know to be able to write the code that gets the query string for a GET request:

# 

# First get the request method
$method = $ENV{'REQUEST_METHOD'};

if ($method eq "GET" ) {        # NOTICE I USE "eq" NOT "==" !!!!!!
    $request = $ENV{'QUERY_STRING'};
}

If the request method is "POST" we need to read the request from standard input, and we need to know how much to read. We can't read until EOF since we won't ever see EOF ! (stdin is actually connected back to the web server and the server won't ever tell us we've reached the end of the data). Perl has a read command that we can tell how many bytes (characters) we want to read:

# First get the request method
$method = $ENV{'REQUEST_METHOD'};

if ($method eq "POST" ) {        # NOTICE I USE "eq" NOT "==" !!!!!!
    $size = $ENV{'CONTENT_LENGTH'};
    read(STDIN,$query,$size);    # read $size bytes in to $query
}

Splitting up the query and URL-decoding

If the CGI program expects the query to be generated by an HTML form, the query string is a URL-encoded sequence of name/value pairs. Each name/value pair is represented with the syntax name=value and the sequence of these strings are glued together with the &character.

We must split the query string up in to name/value pairs before attempting to do any URL-decoding, otherwise we might end up introducing a new & or = that would confuse the splitting process later. To split the query string on the & character we can just do this:

#  $query holds the query string

@pairs = split("&",$query);

# @pairs is now an array that holds a string like "name=value" in each
# array location.

We can now work on each of the name/value pairs in @pairs by splitting on the "=" character:

# @pairs is an array that holds a string like "name=value" in each
# array location.

foreach $i (@pairs) {
    ($name,$value) = split("=",$i);
}

We obviously need to do a little more to save each name/value pair some place we can get at them later. Before we worry about this we need to do URL-decoding on each $name and on each $value.

URL decoding

Recall that each part of the query string is URL-encoded by the browser before being submitted to server as part of an HTTP request. This encoding ensures that there are no spaces in the query, and also makes sure that the name/value pairs can be recognized easily (so if the user enters something like "hi=dave" in a form we can't get something like "name=hi=dave"). The encoding is done as follows: