Where do I get my input from?

Examples using the GET & POST Methods

The examples are explained below.

Let's take a look at the form that was used in the examples:

<FORM METHOD="GET" ACTION="formget.pl">
     Your Name: <INPUT TYPE="text" NAME="name">
     You E-mail: <INPUT TYPE="text" NAME="email">
     <INPUT TYPE="submit">
</FORM>

Now, you expect your CGI (formget.pl) to get the values for name and email somehow... but how? There are two answers to that question. That is because there are two METHODs to submit a <FORM>, POST and GET. In fact, the only difference between the two METHODs lies in the way that the input is given to the script. Here's what happens in each case:

  1. GET
    The input of a GET request is stored in a special Environmental Variable called QUERY_STRING. To access an Environmental Variable from your Perl script, you have to use the %ENV hash that Perl nicely provides. All you need to say is:

$input = $ENV{QUERY_STRING};

and the Form's data will be put to $input.

  1. POST
    The POST method does not put your input in some variable. Instead, the Webserver, upon executing your script will pass the CGI input to the script from STDIN (the STandarD INput). So, all you have to do is to read from the STDIN filehandle to get your input. The only tricky thing is that, an EOF (end-of-file) is not guaranteed at the end of the string. So how do you figure out how much you need to read? Not coincidentally, the server puts the length of the input string into an Environmental Variable, CONTENT_LENGTH. So you have to read CONTENT_LENGTH bytes from STDIN . The line that does this is:

read(STDIN, $input, $ENV{CONTENT_LENGTH});

An entire Form's information can be written in one simple line!  Now try the following, that prints out to the browser the input string it got from the Form:

#!/usr/local/bin/perl

print "Content-type: text/html\n\n";

print $ENV{QUERY_STRING};

OK, I see the example, but this comes all scrambled! So how do I decode it?

CGI input comes in URL Encoded. The general form is the following:

NAME1=VALUE1&NAME2=VALUE2&...&NAMEn=VALUEn

where, NAME1...NAMEn are the names (as in the NAME attribute of the <INPUT> tag in the HTML form) of the input fields and VALUE1...VALUEn are the corresponding values. What the user typed in or selected.

In addition, the resulting string is encoded, by replacing all spaces (" ") with pluses (+)s and replacing certain other characters (like / and ~ and :) with hexadecimal ASCII codes (%2F and %7E and %3A) representing them. Now this looks very  messy, but don't be scared, because with Perl it only takes a couple of lines to decode. So, let's see how it's done:

First of all you'll have to separate each NAME=VALUE pair from the rest. We use the split() function to do that.

@pairs = split(/&/, $input);

The line above simple tells Perl to split up the input string on the & symbol (which is the separator of two pair in URL Encoded Form) and put the list of resulting NAME=VALUE pairs in the Array @pairs.

Then, we will have to take each of those pairs, separate the fieldname from the value, decode them, and store them in a hash (Associative Array) so that each fieldname is the key to its value.

Here's how to do it:

foreach $pair (@pairs) {
     ($name, $value) = split(/=/, $pair);
     $value =~ tr/+/ /;
     $value =~ s/%([\dA-Fa-f]{2})/pack("C", hex($1))/eg;
     $INPUT{$name} = $value;
}

Now, what this does is pretty straightforward. We try each pair in turn, and if it is of the Form NAME=VALUE we store the fieldname and value in two separate variables. Then we replace all pluses (+)s with spaces (" ") and decode hexadecimal sequences. If you don't really follow the regular expressions, don't worry... you don't need to understand how they work, so long as you know how to use them -- you will learn more with time if continue to study Perl. Finally, we put the value we get in an Associative Array with the relevant fieldname as a key.

So, now, all we need to do, is use the Associative Array %INPUT to access our Form's data. For example, the following lines:

print "Content-type: text/plain\n\n";

print "Your Name is $INPUT{name} and your Email is $INPUT{email}

will print to the browser, something like

Your Name is Frank Peter and your Email is frank@sislands.com

or the example form above.

That's basically all you need to know to get started. Trying things out and experimenting is your best bet at learning, so go on and try for yourself...