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.

______________________

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