CGI scripting for forms and data manipulation
Jonathan Morra

What is CGI?
Setting up forms for use with CGI
Using CGI.pm to get basic text data

Getting other types of form data
Checking Data
Manipulating Data
Final Thoughts
Example Code

What is CGI?

CGI stands for Common Gateway Interface. It is basically a way for running scripts to exchange information between the outside world and the user using the Internet as the medium. CGI scripting can be done in many languages, including Java, C, or Perl. However, because mainly of Perl's portability, its ease of interaction with outside file systems, and its widespread availability, this is the main language in which CGI scripting is done.

Setting up forms for use with CGI

Forms are done using the standard HTML format. The basic tags associated with forms are action (the CGI script to be called) and method (either get or post). For this example, get is used as a standard. Once the form is written in HTML, getting and manipulating the data is easy. Just write a Perl script and use the CGI.pm module. This is more or less a "Swiss-army knife" for CGI-scripting. This is because with just this tool, one can access almost all of the necessary functions. To use CGI.pm, you have to first tell Perl that you will be using CGI, then create a new CGI object, then set the max size of the posts and disable uploads. This is done with the following lines...


#!/usr/bin/perl --

use CGI;

$CGI::DISABLE_UPLOADS = 1;
$CGI::POST_MAX = 102_400;

my $q = new CGI;


Now $q is the CGI object.

Using CGI.pm to get basic text data

The first thing to do after creating the CGI object is to output the header. This is done by a function call just like this one...


$q->header( "text/html");


After that is done, accessing the information passed by the HTML form is easy. The name tag associated with each HTML form is just one argument for the method param used with the CGI object. An easy example is suppose a text line was created in the HTML code using this...


<INPUT TYPE="text" NAME="stuff">


Then in order to access what the user typed into this text field, all that is needed is this...


$information = $q->param("stuff");


The method param has an argument for each one of the names of the form fields.

Getting other types of form data

Getting other types of HTML form data follows much the same path as the plain text. For example, in order to get radio button information, just assign a temporary variable to the param with the name of the radio group buttons. Then just check if the temporary variable is equal to the given name of the radio button. Check boxes are done by checking if the name of it exists (use Perl's defined function).

Checking Data

Sometimes it is desired for the form to check to make sure that a certain input is in a desired form. This can easily be done using basic Perl logic. One example is a date. Suppose that you only want the data entered in the form mm/dd/yy. Then just use Perl's text matching abilities to make sure that the input is in the correct format. Then you could quit the CGI script and output an error to the user saying that they entered the information incorrectly. An example of the CGI script would be this...

$date = $q->param("date");
if ($date !~ @^\d{2}/\d{2}/\d{2}$@ ) {
print "You have to enter in the date in the form mm/DD/yy. Please try again";
exit(0);
}

Manipulating Data

Once you've acquired the data, there are many options to do with it. One of the most basic functions is to output the data to a text file. In order to do this, simply open a standard Perl file handle and then print any formatting and data to this file. Another option is to create a different file for each person who completes the form. This can be done by making the file names out of parts of the data gathered from the user. For example, if there are two fields in the form called lname (last name) and fname (first name) then the following example will create a different file for each person...

$lname = $q->param("lname");
$fname = $q->param("fname");
$filename = "$lname, $fname";
open (FILE, $filename) or die "cannot open $filename: $!";
flock(FILE, 2) or die "cannot lock file";

The or statements are just as a precaution, and in the normal use of the script should never come into play. The lock statement is needed so that two people cannot upload to the same file at the same time. Make sure to unlock the file once you are done by changing flock to 8.

Any other data manipulation, such as comparisons or matching can be done with standard Perl logic, once the data has all been read in.

Final Thoughts

A few more things to take care of are to make sure to chmod the CGI file to 711, and to chmod the output file(s) to 700. This will prevent outside people from reading your code or the information gathered. Also, a good thing to do is to have a few simple statements that allow the user to go to a specific place once the form is complete. A brief example of this is...

print "Your information has been entered.<BR>";
print "<BR><A HREF=\"http://www.jhu.edu/">Back to main
page</A>";

flock (FILE, 8) or die "cannot unlock $file";
close FILE;
exit(0);

Example Code

# This program gets the user's first and last name, their two favorite
# numbers and their favorite operation. It then performs the operation
# using the two numbers, and outputs the result to the user with his/her
# last name, and a link back to the previous page.

#!/usr/bin/perl --

use CGI;

$CGI::DISABLE_UPLOADS = 1;
$CGI::POST_MAX = 102_400;

my $q = new CGI;
print $q->header( "text/html" );

$lname = $q->param("lname"); # We have a text field for the last name
$fname = $q->param("fname"); # We have a text field for the first name

$first_number = $q->param("num1"); # Text fields for the first and
$second_number = $q->param("num2"); # second numbers

if ($first_number !~ /^\d*$/) { # Check that number 1 is a number
print "You must enter a number for your first favorite number";
print "Click <a href="test.html">here</a> to try again";
exit(0);
}

if ($second_number !~ /^\d*$/) { # Check that number 2 is a number
print "You must enter a number for your second favorite number";
print "Click <a href="test.html">here</a> to try again";
exit(0);
}
# If either of these checks fail then ask the user to try again


$operation = $q->param("operation"); # Get the type of operation

# These if statements see what the operation is, then do the operation,
# t
hen output the result to the user, and finally provide a link back
# the main page

if ($operation eq "add") {
$output = $first_number + $second_number;
print "$fname $lname the result of $first_number + $second_number is $output";
print "Click <a href="upe website.html">here</a> to return to the previous page";
exit(0);
}

elsif ($operation eq "sub") {
$output = $first_number - $second_number;
print "$fname $lname the result of $first_number - $second_number is $output";
print "Click <a href="upe website.html">here</a> to return to the previous page";
exit(0);
}

elsif ($operation eq "mult") {
$output = $first_number * $second_number;
print "$fname $lname the result of $first_number * $second_number is $output";
print "Click <a href="upe website.html">here</a> to return to the previous page";
exit(0);
}

elsif ($operation eq "div") {
$output = $first_number / $second_number;
print "$fname $lname the result of $first_number / $second_number is $output";
print "Click <a href="upe website.html">here</a> to return to the previous page";
exit(0);
}

# If the user does not choose an operation, then it asks him/her to do so

else {
print "You need to choose an operation in order to complete the form";
print "Click <a href="test.html">here</a> to try again";
exit(0);

}

3/25/04