A Short Form Element Demonstration

only for RuBoard - do not distribute or recompile

Let s write a short script, elt_demo.pl, that shows how to use the material discussed in the earlier part of this chapter.The script is simple but does several things:

  • It generates a form that includes an instance of each type of element we ve discussed so far. You can select or fill in elements and then submit the form.

  • The script is self-referential; it not only generates the form, it also processes it by causing itself to be invoked when you select the Submit button.

  • elt_demo.pl examines its CGI environment using param() to determine whether information for a submitted form is present. If so, it extracts and displays that information to enable you to see how various types of fields are received by the Web server.

  • The script demonstrates a few rudimentary techniques for processing information received from the form. If the single-line text field contains information, it characterizes the value. If a file was uploaded, it prints some information about the file such as its name and size.

  • It shows how CGI.pm s sticky form behavior enables you to generate a form that is initialized using values from the previous form. The form includes a check box that enables you to turn this behavior on or off so you can see its effect.

You may find it useful to install the script from the book s source distribution so that you can play with it. Modify the parameter lists for the various form element generating calls to see what effect your modifications have.

The elt_demo.pl script begins with a fairly predictable preamble:

 #! /usr/bin/perl -w  # elt_demo.pl - form element demonstration  # This script shows how to generate form elements using CGI.pm calls.  # It also shows how to recover form element values from submitted forms.  use strict;  use CGI qw(:standard escapeHTML);  print header (),      start_html (-title => "Form Element Demonstration", -bgcolor => "white"); 

The code that generates the form first determines whether to use sticky form behavior, so that we can tell whether to populate the form with its previous values. The default is off, of course, because the value is controlled by a check box in the form itself, and the first time you invoke the script, no form elements have any values:

 my $sticky = defined (param ("sticky")); 

Next, we generate the form using a long print statement. The form begins with start_multipart_form() rather than start_form() because the form includes a file-upload field. Note how each call to generate an element within the form includes an override parameter that reflects the current state of the sticky check box. The exceptions to sticky behavior are: The sticky check box itself, which is deliberately always sticky so that it always retains its previous setting; the file upload field, because CGI.pm won t initialize it anyway; and the Submit and Reset buttons.

 print start_multipart_form (-action => url ()),          hidden (-name =>"hidden field",                  -value => "hidden value",                  -override => !$sticky),          p ("Text field:"),          textfield (-name =>"text field", -override => !$sticky),          p ("Password field:"),          password_field (-name =>"password field", -override => !$sticky),          p ("Text area:"),          textarea (-name =>"text area",                    -rows => 3,                    -cols => 60,                    -wrap => "virtual",                    -override => !$sticky),          # no override parameter here; CGI.pm wouldn't initialize it anyway          p ("File upload field:"),          filefield (-name =>"file field", -size => 60),          p ("Radio button group:"),          radio_group (-name => "radio group",                          -values => ["a", "b", "c"],                          -labels => {                             "a" => "Button A",                              "b" => "Button B",                              "c" => "Button C"                              },                          -override => !$sticky),          p ("Checkbox group:"),          checkbox_group (-name => "checkbox group",                          -values => ["a", "b", "c"],                          -labels => {                             "a" => "Box A",                              "b" => "Box B",                              "c" => "Box C"                              },                          -override => !$sticky),          p ("Popup menu:"),          popup_menu (-name => "popup menu",                      -values => ["a", "b", "c", "d", "e", "f"],                      -labels => {                         "a" => "Item A", "b" => "Item B", "c" => "Item C",                          "d" => "Item D", "e" => "Item E", "f" => "Item F"                          },                      -override => !$sticky),          p ("Single-pick scrolling list:"),          scrolling_list (-name => "scrolling list single",                          -size => 3,                          -values => ["a", "b", "c", "d", "e", "f"],                          -labels => {                             "a" => "Item A", "b" => "Item B", "c" => "Item C",                              "d" => "Item D", "e" => "Item E", "f" => "Item F"                              },                          -override => !$sticky),          p ("Multiple-pick scrolling list:"),          scrolling_list (-name => "scrolling list multiple",                          -size => 3,                          -multiple => 1,                          -values => ["a", "b", "c", "d", "e", "f"],                          -labels => {                             "a" => "Item A", "b" => "Item B", "c" => "Item C",                              "d" => "Item D", "e" => "Item E", "f" => "Item F"                              },                          -override => !$sticky),          br (), br (),          # this checkbox is deliberately always sticky          checkbox (-name => "sticky", -label => "Use sticky fields"),          br (), br (),          submit (-name => "choice", -value => "Submit"),          " ",    # separate buttons with a space          reset ("Reset form"),          end_form (); 

The elt_demo.pl script also includes code that checks to see whether a form was submitted. If so, it displays the information that it finds. escapeHTML() is used extensively here. The values we re printing might contain special characters, but CGI.pm won t automatically escape them for us because we re not generating form elements at this point:

 # Determine which form elements are present from previous form  print hr (), p ("Form element names and values submitted in previous form:");  my @names = param ();  # get list of parameter names  if (!@names)        # initial script invocation  {     print p ("(no elements present)");  }  else                # subsequent script invocation  {     # present a general display of the information from the submitted form      my @item = ();      foreach my $name (@names)      {         my @val = param ($name);          # if element is multiple-valued, display as "[val1, val2, ...]"          $val[0] = "[" . join (", ", @val) . "]" if @val > 1;          push (@item, escapeHTML ("$name: ($val[0])\n"));      }      print ul (li (\@item)); # print values within <ul> ... </ul> list      # perform a couple of field-specific checks      if (my $val = param ("text field"))     # check single-line text field      {         print p ("The text field contains a value '"                  . escapeHTML ($val)                  . "'. This value satisifies the following conditions:");          $val =~ s/^\s+//;       # trim leading/trailing whitespace          $val =~ s/\s+$//;          @item = ();          # is it empty?          push (@item, "empty: " . ($val eq "" ?? "yes" : "no"));          # is it an integer?          push (@item, "integer: " . ($val =~ /^[+-]?\d+$/ ? "yes" : "no"));          # is it a date? (this is a very WEAK date check!)          push (@item, "date: " . ($val =~ /^\d+\D\d+\D\d+$/ ? "perhaps" : "no"));          print ul (li (\@item)); # print list showing test results      }      if (my $file = param ("file field"))    # check file upload field      {         print p ("A file was chosen for uploading.  Its name is '"                  . escapeHTML ($file)                  . "', and its size is " . (stat ($file))[7] . " bytes."                  . " The upload attributes are:");          @item = ();          for my $attr (keys (%{uploadInfo ($file)}))          {             push (@item, escapeHTML ("$attr: " . uploadInfo ($file)->{$attr}));          }          print ul (li (\@item)); # print list showing upload attributes      }  }  print hr (); 

After printing the list of the parameter names and values, the script demonstrates some simple tests of the input. If there is a value in the single-line text field, elt_demo.pl performs some simple characterization of the value:

  • Is it empty? (Yes, unless it contains a non-whitespace character.)

  • Is it an integer? (Yes, if it s all digits, optionally preceded by a plus or minus sign.)

  • Does it look like a date? (Yes, if it contains three numeric components separated by non-numeric characters; the script prints perhaps rather than yes because this test is not very rigorous.)

The code that checks whether or not the text field value looks like an integer actually contains a bug, which you can demonstrate by entering a value consisting of a single digit 0. In this case, elt_demo.pl doesn t even recognize that the field contains a value! The reason this happens is that the string "0" evaluates to false in a Boolean context. The following test does not have this problem:

 if (defined (my $val = param ("text field"))) ... 

Be sure to perform the proper test when you write your own form-processing code, to avoid falling prey to this problem.

If a file was uploaded, the script prints the file s name, its size, and the upload attributes. The value of the file-upload field contains the filename, so we can treat it as a string for printing purposes, and we can pass it to uploadInfo(), a function provided by CGI.pm that provides information about the file. uploadInfo() returns a reference to a hash of attribute names and values, so we iterate through the hash keys to get the values.

The value returned by CGI.pm for a file-upload parameter actually has a dual purpose. Not only can you treat the value as a string containing the filename, you also can use it as a file handle to read the file or to pass to other file-related functions. That being so, we pass the handle to stat() to access an array of values describing the file. (We re interested only in the eighth element, which indicates the file size.) We don t do anything with the file itself, but that s harmless; the contents are stored in a temporary file, and the Web server automatically deletes it when the script terminates.

only for RuBoard - do not distribute or recompile


MySQL and Perl for the Web
MySQL and Perl for the Web
ISBN: 0735710546
EAN: 2147483647
Year: 2005
Pages: 77
Authors: Paul DuBois

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net