Here are the followups to ambiguous points or unanswered questions raised in the previous week of class.
First Item: We discussed two ways to get the size of an array by assigning it to a scalar: either @array or $#array. Here is the final word on how this works, presented in the form of this simple program:
#!/usr/bin/perl -w @array = qw(Phil Dan Andy); $scalar = @array; print '$scalar = @array : ', $scalar, "\n"; # prints '3' $scalar = $#array; print '$scalar = $#array : ', $scalar, "\n"; # prints '2'
So, as we see, @array will give you the total number of items in the array (or in other words, one past the end--suitable for the condition of a for loop), and the $#array method will get you the index of the last element in the array.
Second Item: I have amended last week's notes to include a third CGI specification. Be sure to check that out if you haven't attended the lectures.
In order for the server to communicate special information to the remote agent (usually a browswer, but occasionally a proxy server), the server sends Server Headers with each page, which are text strings that proceed the opening <HTML> line.
Most of the time, these strings are printed implicitly by the server, but they can also be sent as META tags in HTML pages. In a CGI program, you exercize Olympian powers regarding what strings you can send.
Important Point: Each Server Header string must be followed by a carriage return. Once you are done printing out all the Server Headers, you must put one more carriage return.
A header with only one line would look like this:
Content-type: text/html <HTML> <HEAD> <TITLE> Escorial Treatiste on the Deposition of Rutabegas </TITLE> . .
A header with more than one line would look like this:
Content-type: text/html Pragma: no-cache <HTML> <HEAD> <TITLE> Escorial Treatiste on the Deposition of Rutabegas </TITLE> . .
Get it?
You can find a full list of Header Field Definitions on the W3C's Website . The following is a list of the most common Server >Headers:
Note: You will not always be printing text/html as the type of content. You can output any content specified in the HTTP_ACCEPT environment variable.
There are doubtless other strings that you could put following the Pragma: text, but I don't know what they are.
You can look at the complete list of Status Codes on the W3C Website.
The front end to most CGI programs (and the front-end to your assignment #3) is an HTML form. Forms display widgets inside the browser and allow you to enter information.
A sample form looks like this:
<FORM ACTION="cgi-bin/myprog.cgi" METHOD="GET"> Name: <INPUT type="text" NAME="username" SIZE=40> <BR> Email: <INPUT type="text" NAME="email" SIZE=40> <BR> Password: <INPUT type="password" NAME="password" SIZE=40> <BR> <INPUT type="hidden" NAME="hiddenfield" VALUE="hiddentext"> <BR> <INPUT type="submit" VALUE="Submit"> </FORM>
Here's what all that means:
In the example above, I'm using mostly text controls, but different kinds of text controls: Some are plain text, one is a password, and one is hidden.
See an example form in action right here .
For a full listing of the kinds of widgets you can use inside FORM tags, have a look at the HTML FORMs documentation on the W3C Website. We will go over this document in more detail on the next lab night. I highly recommend that you look at this documentation, because it contains a lot of good examples on how to use forms.
For an example of a really big form, look here
Somehow, your HTML form needs to be able to send its information to your CGI program. Here's how it's done:
"Query Strings" are big, mangled-looking strings that get passed to your CGI program from your HTML form either by a GET or a POST method. Another way of putting it is: The way your HTML form communicates with your CGI program is with Query Strings.
An example query string looks like this:
http://osiris/~mark/cgi-bin/myprog.cgi?username=Barney+Fife&email=barney%40mayberry.org&password=secret&hiddenfield=hiddentext
The format goes like this:
The following table outlines the subtle differences. We will go over these at greater length in class.
Method | Description | Pro | Con |
---|---|---|---|
GET | The form variables are sent with the GET request to the Web server and show up in the URL text field in your browser. | Handy for doing "canned" queries, letting the user either enter in the CGI variables by hand, or use those variables in a link. | The size of the string you can send to the Web server is limited to 256(?) characters. |
POST | The form variables are sent after the URL request and do not show up in the URL text field in your browser. | Handy when you need to send lots of form variables to the CGI program. | Susceptible to buffer overflows if you're not careful. |
See also: Form
Submission Methods on the W3C's Website.
Example Query String Parser
The following hunk of Perl code will handle any kind of query string you care to pass it (using either GET or POST method) and will build a %FORM hash that contains the form variables. You should put this close to the top of your program.
# Determine the request method if ($ENV{REQUEST_METHOD} eq 'GET') { $query = $ENV{QUERY_STRING}; } elsif ($ENV{REQUEST_METHOD} eq 'POST') { read(STDIN, $query, $ENV{CONTENT_LENGTH}); } else { print "Error: Unrecognized method.\n"; } # Split up the query string into key/value pairs (i.e. username=Fred) @pairs = split /&/, $query; foreach $pair (@pairs) { # Split the pair into a key and value ($key, $value) = split /=/, $pair; # Substitute plus signs for whitespace $key =~ tr/+/ /; $value =~ tr/+/ /; # Substitue hexidecimal characters for their decimal equivalents # (The most common substitutions you make are for spaces, slashes, # and colons, since these characters either have special meanings # or are not allowed in URLs.) $key =~ s/%([\da-fA-F]{2})/pack "C", hex($1)/eg; $value =~ s/%([\da-fA-F]{2})/pack "C", hex($1)/eg; # Add the key and value to the %FORM hash if (exists $FORM{$key}) { # If the FORM key already exists, make a comma delimited # list of the values and assign it to that key. # (This is the case for menus & checkboxes.) $FORM{$key} = join ',', $FORM{$key}, $value; } else { $FORM{$key} = $value; } }We will go over the details of how this works in class.
Changelog:
4/8/99 - Initial Revision
4/9/99 - Corrected a few bugs found in class, added the bigform.html link