CGI Programming

So you're gathering information from your surfers; what now?
Required Fields

What if we want to make sure that users have filled out certain fields? This is particularly important when we are collecting data about visitors to a site, and want to make sure that we receive their names, addresses and other vital data. A simple way to do that is to create a list, @required_fields, in which the required fields are listed:

my @required_fields = ("name",
                              "email",
                              "address");

If you simply want a generic message indicating that one or more required fields haven't been filled out, you can add the following subroutine at the bottom of the program file:

sub missing_field
{
  # 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)");
  # Tell the user what the error is
  print "<P>At least one required ";
  print "field is missing.</P>\n";
  # Finish up the HTML
  print $query->end_html;

}

We can then insert the following code into the program itself, just before we open the file—since there isn't any reason to open the file if we are simply going to close it again:

foreach $field (@required_fields)
{
  # Make sure that the field contains more than
  # just whitespace
  &missing_field if
  ($query->param($field) !~m/\w/);
  exit;
}

The above code will indeed do the trick, but gives a generic error message. Wouldn't it be better to tell the user which field contains the error? We can do that by modifying missing_field such that it takes an argument, as follows:

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 ";
  print "required fields:</P>\n";
  print "<ul>\n";
  # Iterate through the missing fields, printing
  # them foreach $field (@missing_fields)
  {
    print "<li> $field\n";
  }
  print "</ul>\n";

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

We then modify the loop that checks for required fields:

foreach $field (@required_fields)
{
  # Add the name of each missing field
  push (@missing_fields, $field) if
   ($query->param($field) !~ m/\w/);
}
# If @missing_fields contains any elements, then
# invoke the error routine
&missing_field(@missing_fields)
  if @missing_fields;

If we want to get really fancy, we can provide English names for each of the required fields, so that users don't have to suffer through the names we used with the HTML form. We can do that by using associative arrays:

$FULLNAME{"name"} = "your full name";
$FULLNAME{"email"} = "your e-mail address";
$FULLNAME{"address"} = "your mailing address";

Then we modify the foreach loop in &missing_fields such that it prints the full name of the missing field, rather than the name associated with it on the HTML form:

# Iterate through the missing fields, printing
# them foreach $field (@missing_fields)
{
  print "<li> $FULLNAME{$field}\n";
}
print "</ul>\n";
Dying with Style

Remember that die statement we put in our original program? Well, think about what will happen if that part of the program is ever truly invoked—die will produce an error message, which is a good thing. But that error message will be sent to our web browser, before the HTML header, giving us the dreaded “Server error” message, indicating that something (but not saying what that something is) has gone wrong with our script.

More useful would be a routine that printed the error message to the screen. For example, we could add the following subroutine:

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;
}

And now, we can rewrite the “open” statement as follows:

open (FILE, ">&gt:$filename") ||
  &error_opening_file($filename);

You probably don't want to tell your users your program couldn't open a particular file—not only do your users not care, but you don't need to tell them which files you are using. A more user-friendly version of error_opening_file could tell the user that the server is experiencing some trouble, or is undergoing maintenance or give a similar message that doesn't broadcast catastrophe to the world.

______________________

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState