CGI Programming

So you're gathering information from your surfers; what now?
Bringing It All Together

The final version of the program, with (a) required fields, (b) full-English descriptions of those fields, and (c) a better error message when we cannot open the file, reads as follows:

#!/usr/local/bin/perl5
# We want to use the CGI module
use CGI;
# Set the filename to which we want the elements
# saved
my $filename = "/tmp/formcontents";
# Set the character that will separate fields in
# the file
my $separation_character = "\t";
# In what order do we want to print fields?
my @fields = ("name",
              "email",
              "address",
              "country",
              "sex");
# Which fields are required?
my @required_fields = ("name",
                       "email",
                       "address");
# What is the full name for each required field?
$FULLNAME{"name"} = "your full name";
$FULLNAME{"email"} = "your e-mail address";
$FULLNAME{"address"} = "your mailing address";
# Create a new CGI object
my $query = new CGI;
# ---------------------------------------------
# Make sure that all required fields have arrived
foreach $field (@required_fields)
{
    # Add the name of each missing field
    push (@missing_fields, $field)
    if ($query->param($field) !~ m/\w/);
}
# If any fields are missing, invoke the error
# routine
&missing_field(@missing_fields)
  if @missing_fields;
# ---------------------------------------------
# Open the file for appending
  open (FILE, "7gt;>$filename") ||
  &error_opening_file($filename);
# Grab the elements of the HTML form
@names = $query->param;
# Iterate through each element from the form,
# writing each element to $filename. Separate
# elements with $separation_character defined
# above.
foreach $index (0 .. $#fields)
{
    # Get the input from the appropriate HTML
    # form element
    $input = $query->param($fields[$index]);
    # Remove any instances of
    # $separation_character
    $input =~ s/$separation_character//g;
    # Now add the input to the file
    print FILE $input;
    # Don't print the separation character after
    # the final element
    print FILE $separation_character if
    ($index < $#fields);
}
# Print a newline after this user's entry
print FILE "\n";
# Close the file
close (FILE);
# ---------------------------------------------
# Now thank the user for submitting their
# information
# Print an a appropriate MIME header
print $query->header("text/html");
# Print a title for the page
print $query->start_html(-title=>"Thank you");
# Print all of the name-value pairs
print "<P>Thank you for submitting ";
print "the form.</P>\n";
print "<P>Your information has been ";
print "saved to disk.</P>\n";
# Finish up the HTML
print $query->end_html;
# ---------------------------------------------
# Subroutines
sub missing_field
{
    # Get our local variables
    my (@missing_fields) = @_;
    # Print an a appropriate MIME header
    print $query->header("text/html");
    # Print a title for the page
    print $query->start_html(-title=>
    "Missing field(s)");
    print "<P>You are missing the following
    required fields:</P>\0";
    print "<ul>\n";
    # Iterate through the missing fields,
    # printing them
    foreach $field (@missing_fields)
    {
        print "<li> $FULLNAME{$field}\n";
    }

    print "</ul>\n";

    print "</ul>\n";

    # Finish up the HTML
    print $query->end_html;

    exit;
}
sub error_opening_file
    {
        my ($filename) = @_;
        # Print an a appropriate MIME header
        print $query->header("text/html");
        # Print a title for the page
        print $query->start_html(-title=>
        "Error opening file");
        # Print the error
        print "Could not open the file
        \"$filename\".</P>\n";
        # Finish up the HTML
        print $query->end_html;
        exit;
    }
Creating a Guest-book

One of the most common CGI applications on the Web is a “guest-book”, which allows visitors to a site to sign in, leaving their names, e-mail addresses and short notes. We can easily construct such a program, using the basic framework seen in the above programs. The only difference between the “guestbook” program and the programs we have seen so far is that the guest-book must be formatted in HTML in order for users to be able to read it in their browsers.

Here is a very simple guest-book program that is virtually the same as the previous program we saw:

<HTML>
<Head>
<Title>Guestbook entry</Title>
</Head>
<Body>
<H1>Guestbook entry</H1>
<Form action="/cgi-bin/guestbook.pl"
    method=POST>
<P>Name: <input type=text name="name"
    value=""></P>
<P>E-mail address: <input type=text name="email"
value=""></P>
<input type=submit>
</Form>
</Body>
</HTML>

The following program is the same as the one above, except that it saves data to the “guestbook.html” and formats the data in HTML.

#!/usr/local/bin/perl5
# We want to use the CGI module
use CGI;
# Set the filename to which we want the elements
# saved
my $filename =
"/home/reuven/Consulting/guestbook.html";
# Set the character that will separate fields in
# the file
my $separation_character = "</P><P>";
# In what order do we want to print fields?
my @fields = ("name", "email");
# Which fields are required?
my @required_fields = ("name", "email");
# What is the full name for each required
# field?
$FULLNAME{"name"} = "your full name";
$FULLNAME{"email"} = "your e-mail address";
# Create a new CGI object
my $query = new CGI;
# ---------------------------------------------
# Make sure that all required fields have arrived
foreach $field (@required_fields)
{
  # Add the name of each missing field
  push (@missing_fields, $field) if
  ($query->param($field) !~ m/\w/);
}
# If any fields are missing, invoke the error
# routine
&missing_field(@missing_fields) if
  @missing_fields;
# ----------------------------------------------
# Open the file for appending
open (FILE, ">>$filename") ||
  &error_opening_file($filename);
# Grab the elements of the HTML form
@names = $query->param;
# Iterate through each element from the form,
# writing each element to $filename. Separate
# elements with $separation_character defined
# above.
foreach $index (0 .. $#fields)
{
  # Get the input from the appropriate HTML form
  # element
  $input = $query->param($fields[$index]);
  # Remove any instances of $separation_character
  $input =~ s/$separation_character//g;
  # Now add the input to the file
  print FILE $input;
  # Don't print the separation character after the
  # final element
  print FILE $separation_character if
  ($index < $#fields);
}
# Print a newline after this user's entry
print FILE "<BR><HR><P>\n\n";
# Close the file
close (FILE);
# -------------------------------------------
# Now thank the user for submitting his
# information
# Print an a appropriate MIME header
print $query->header("text/html");
# Print a title for the page
print $query->start_html(-title=>"Thank you");
# Print all of the name-value pairs
print "<P>Thank you for submitting ";
print "the form.</P>\n";
print "<P>Your information has been ";
print "saved to disk.</P>\n";
# Finish up the HTML
print $query->end_html;
# --------------------------------------------
# Subroutines
sub missing_field
{
  # Get our local variables
  my (@missing_fields) = @_;
  # Print an a appropriate MIME header
  print $query->header("text/html");
  # Print a title for the page
  print $query->start_html(-title=>"
  Missing field(s)");
  print "<P>You are missing the ";
  print "following required fields:</P>\n";
  print "<ul>\n";
  # Iterate through the missing fields, printing
  # them
  foreach $field (@missing_fields)
    {
        print "<li> $FULLNAME{$field}\n";
        }
  print "</ul>\n";
  print "</ul>\n";
  # Finish up the HTML
  print $query->end_html;
  exit;
}
sub error_opening_file
{
  my ($filename) = @_;
  # Print an a appropriate MIME header
  print $query->header("text/html");
  # Print a title for the page
  print $query->start_html(-title=>
  "Error opening file");
  # Print the error
  print "Could not open the ";
  print "file \"$filename\".</P>\n";
  # Finish up the HTML
  print $query->end_html;
  exit;
}

The above program will take input from the HTML form and save the data in an HTML-formatted file. If that file is accessible from the web server, your users should be able to view others' entries in the guest-book.

Reuven M. Lerner (reuven@the-tech.mit.edu) (reuven@netvision.net.il) has been playing with the Web since early 1993, when it seemed like more of a fun toy than the world's Next Great Medium. He currently works from his apartment in Haifa, Israel as an independent Internet and Web consultant. When not working on the Web or informally volunteering with school-age children, he enjoys reading (just about any subject, but especially computers, politics, and philosophy—separately and together), cooking, solving crossword puzzles and hiking.

______________________

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix