Print this Article (NS4)
Netscape Navigator
Internet Explorer
Opera
Neoplanet

Forums
HTML
General
Site Dev
Programming
Flash
Grafix (Art)

Laboratory
Smart HTML
Color Lab
Generators

Contents
Simple CGI
  1. Hello World
  2. Print function
  3. Quoting, EOF
  4. Metacharacters
  5. Special Characters
Perl Basics 1
  1. Variables
  2. Arrays
  3. Hashes
  4. Split function
  5. Subroutines
  6. Defaults
Form CGI
  1. Loops
  2. Conditions
  3. Boolean Statements
  4. Pattern Matching
Time CGI
  1. Local Time
  2. GM Time
  3. time function
Perl Basics 2
  1. Reading Files
  2. Writing Files
  3. Including Files
  4. chop function
  5. chomp function
Guestbook CGI

Redirect CGI

Poll CGI

  1. Giving Commands
  2. Voting
  3. Results Display
  4. Adding Your Vote
Password CGI
  1. Authentification
  2. Multiple Users
  3. Encryption
Mailing List CGI
  1. Sendmail
  2. Multiple Recipients
Unlimited Subdomains CGI

News Grabber CGI

  1. LWP::Simple
Message Board CGI (Part 1)

Back to the Top


Perl Case Study - Form CGI
By Lisa Hui

A short introduction is on order for the leap into this programming void. The purpose of the following CGI script is to receive data sent from a form. (This script can thus be called via the ACTION attribute in a <FORM> but that is not necessary to pass data!) The data is automatically URL encoded (certain characters are substituted with a corresponding code). This case study piece is heavily commented due to the ambiguous nature of the perl code.

#!/usr/local/bin/perl
#################
# File Name: form.cgi

# Determining whether or not the <FORM> method is GET or POST
# if it is GET, that means all the data was appended to the URL
# if it is POST, all the data was put into STDIN, a data buffer
if ($ENV{"REQUEST_METHOD"} eq 'GET') { $buffer = $ENV{'QUERY_STRING'}; }
else { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }

# All the data has now been copied into the variable called $buffer
# The purpose of this is to associate each set of name of form field
# with the data entries in the form field
@pairs = split(/&/, $buffer);

foreach $pair (@pairs) {
      ($name, $value) = split(/=/, $pair);

      $value =~ tr/+/ /;
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

      $FORM{$name} = $value;
}

#################
# An associative array (hash) called %FORM was created to
# store the value pairs. Now you can get the data from a
# form field simply by calling it by name. If you had a form
# that was like <INPUT Type="text" Name"YourName">
# this piece of data is stored in $FORM{'YourName'}.
# This is derived from the NAME and VALUE (pair) attributes in
# form input fields.
#################
# Print out all the form data on a results page
# See the form and associate its values to this page.

print qq~
<HTML>
  <HEAD>
     <TITLE>$FORM{'title'}</TITLE>
  </HEAD>
<BODY>
Name: $FORM{'YourName'}<br>
How are you today? $FORM{'feeling'}<br>
Have you been able to understand this tutorial? $FORM{'understand'}<br>
Comments: $FORM{'comments'}
</BODY>
</HTML>
~;


See this script in action: form.cgi (POST method) or form.cgi (GET method)

Since I we've only briefly gone through the parsing process, let's take a closer look at the foreach loop:

foreach $pair (@pairs) {
      # Each pair has been stored as $name=$value so now we split them
      ($name, $value) = split(/=/, $pair);

      # $value's with more than one word may have a + sign joining them together
      # this line will replace the + with a space.
      $value =~ tr/+/ /;

      # pattern matching and substitution to decode the URL encoded value
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

      # Associate the $name and $value pair using hash syntax
      # As the foreach loops through all the pairs of data, they will be added to the
      # hash %FORM
      $FORM{$name} = $value;
}

You may have noticed that I didn't add these comments in the actual script printed at the top. (Only because adding comment lines in loops will result in errors messages.)

Since we've gone over hashes and splitting data, the elements that may have not been so familiar are the looping and patternmatching, although looping has a very literal type of diction.

Looping

There are three major types of loops, which are theoretically similar to each other. In most cases, it will be a matter of preference.

While would probably be the simplest to work with. In a primitive sort of English, it is basically saying "While this condition is true, perform these set of instructions again and again (checking during each iteration whether the condition is true)." In Perl-speak, the schematic becomes:

while (condition is true) {
  perform these actions
}

Nevertheless, all three are essentially the same. In a foreach loop, the idea is that you iterate these actions "for each element in an array." The schematic:

foreach $element(@array) {
  perform these actions
}

For is a handy loop because it allows you to display all the initialized variables, the condition, and the incremeter all at the beginning. Check below to see what I mean:

for (intialized values; condition; increment) {
  perform these actions
}

I'm not going to go over for syntax here, but you can find the explanation in the C++ tutorial (what a coincidence, they use the same syntax for this loop!).

What could the condition be? Anything that would evaluate to a "true" or "false," 1 or 0, filled or unfilled. Let's take a very simple example in which the variable is 0 - or false - and  the action (printing the value of the condition) are not performed:

$condition = 0;
while ($condition) {
  print $condition;
}

If you ever write in an "absolute" condition (which always causes the loop to reiterate), you may find the last and exit; commands useful. Last works like the C++ command break; It will  "break" out of the loop and continue on with the program. (Exit, on the other hand, will end the execution of the program.)

$i = 0;
while (true) {
   if ($i eq 100) { last }
   $i++; #increment the variable
}

A tip: you can negate the value of the condition (reverse its value) by putting an exclamation in front of it. !true is the same as writing false.

Below is an example of a while loop that checks if the STDIN buffer is filled;

while (<STDIN>) { print; }

Notice that print automatically prints out each line of STDIN and the condition is that "while STDIN is still filled with some data." You could have set each line of STDIN to a variable and then printed out the variable, but either way should work: while($line = <STDIN>) { print $line; }

Let's take this same example with a foreach loop:

@array = <STDIN>;
foreach $line(@array) {
  print $line;
}

And with a for loop; we don't need to "initialize" or "increment" any values, much like the while loop, so we can leave those blank:

for( ;<STDIN>; ) { print; }

Pattern Matching - Part One

Pattern Matching is probably more of a "menial" task, you might say. You tell the script a word or phrase etc that you want to match. If you asked why we would even need it, you just saw an important example in the form.cgi script. We'll get a chance to sneak a peek at some simple ways to translate, substitute, and get to the real gory (and when I say gory, I mean gory!) pattern matching later on in Perl Case Study - Prelude to Search Engine CGI.

translation tr///

substitution s///

pattern match //m

assertions

modifiers


Perl Case Study - Time CGI

©1999 Team 26297 "Ad Infinitum Web." All rights reserved. Any reproduction of this document for commercial or redistribution purposes without the permission of the author is forbidden.