Form Anatomy

only for RuBoard - do not distribute or recompile

Forms simplify the process of collecting information by offering a structured mechanism for visitors to interact with your site. To a limited extent, you can solicit information from users by having them make choices from lists of hyperlinks, but that quickly turns into the Web equivalent of automated telephone answering-system menus. Forms are more effective.

For structured types of information, such as a list of choices, forms enable you to spell out the options explicitly for the user and provide a convenient way for the user to make a selection. Form elements such as check boxes, radio buttons, pop-up menus, and scrolling lists make it easy to display lists or sets such as colors, sizes, age or salary ranges, number of people per household, state names, and so forth. That way users don t have to type so much; they just select the proper item.

For situations where it won t do to use elements that provide only prespecified options, you can allow users to enter free text. If you re providing a form through which customers request product information, you can include a text field so that they can say exactly what they want to know. In a help desk application, you must let clients describe what problem they re having. If you re an elected official and you provide your constituents with a feedback form, you must let them express their concerns. You also can use text input in conjunction with structured elements such as a set of radio buttons. (Label the last button Other and put a text box next to it to handle cases not covered by the other buttons in the set.)

This section provides a description of the elements that make up forms. It discusses both the HTML syntax for these elements and the CGI.pm calls that generate that HTML for you so that you don t have to write it out yourself. For example, a submit button named choice can be written in HTML like this:

 <input type="submit" name="choice" value="Done"> 

The button also can be generated by printing the result of a call to the CGI.pm submit() function:

 print submit (-name => "choice", -value => "Done"); 

CGI.pm enables you to specify function parameters in named fashion, using -paramname => paramvalue format. This format provides a great deal of flexibility, because you can omit optional parameters, and you can specify parameters in any order.

Each CGI.pm function returns a string value, which you can print, assign to a variable, pass to a function, and so forth. The examples in this chapter use print statements. In later chapters, we ll see scripts that construct forms in memory and pass the resulting strings around before printing them.

The discussion here is descriptive rather than exhaustive that is, I describe typical use of the CGI.pm calls, not every possible parameter to every possible call. For more comprehensive background on form syntax, consult a good HTML reference. For information about CGI.pm in particular, consult Lincoln Stein s Official Guide to Programming with CGI.pm or the online CGI.pm documentation. Appendix B, References and Further Reading, lists these and other suggested sources. Also, you can read the installed CGI.pm documentation by running the following command:

 % perldoc CGI 

Beginning and Ending a Form

Forms begin and end with <form> and </form> tags, which are produced by calling start_form() and end_form(). A typical way to generate a form is as follows:

 print start_form (-action => url ());  # ... generate form elements ...  print end_form (); 

start_form() takes several optional parameters action, method, and enctype that determine the attributes written into the <form> tag and that affect how the form is processed. The action parameter indicates the action that the Web server should perform when the user submits the form to send its contents back to the server. Normally this is the URL of the script that processes the form s contents. Often this URL is that of the script that generated the form in the first place; it s idiomatic in CGI.pm programming for a script both to generate a form and to process the contents of the form when the user submits it. This technique is carried out using two principles:

  • When a script generates the form, it specifies itself as the form s action so that it is reinvoked when the user submits the form.

  • The script detects whether it is being invoked for the first or subsequent time by examining the information in the CGI environment. The initial invocation will find no form information present in the environment; subsequent invocations will find the contents of a submitted form.

The use of self-referencing scripts may be idiomatic but it s not required; there is no rule that a form must be generated and processed by the same script. A script can generate a form with an action that names a different script or even an action that is not a script at all. For example, the action parameter might be something like mailto:address if you want the form contents to be encoded and sent as an email message to the given address.

If you specify no action parameter, the default is self_url(), which expands to the URL that was sent by the browser to invoke your script in the first place. If that URL included any parameters (a ? after the script name, followed by name=value pairs), self_url() includes those parameters as well. If you want just the path of the script itself without any parameters, use url() instead. Generally, when you use a script to generate a form as well as to process it, it s best not to specify the action parameter by writing the script s URL literally into the script. By using self_url() or url() instead, CGI.pm determines the URL when the script runs. That way, your script will always generate the proper self-referencing action value even if you rename or move your script, something that is not true if you write the URL literally.

The method parameter controls how form contents are transmitted back to the Web server when the user submits the form. Its value can be POST or GET. With POST, the contents are sent in the body of the request, separate from the URL. With GET, the form contents are appended to the end of the URL sent back to the Web server. GET involves some risk of hitting URL length limitations and possible silent truncation, so generally POST is a better choice. Scripts in this book use POST, which is also the default if you specify no method parameter.

enctype controls how form contents are encoded for transmission. If you don t specify an encoding method, the default is application/x-www-form-urlencoded. This suffices for most situations, with one important exception: If your form includes a file upload field, you should use multipart/form-data instead or files will not upload properly. These encoding type values are available as the constants $CGI::URL_ENCODED and $CGI::MULTIPART. The default for start_form() is $CGI::URL_ENCODED ; if you want to generate a multipart form, you can call start_multipart_form() instead. It accepts the same arguments as start_form(), but uses a default encoding type of $CGI::MULTIPART. This means that in practice you need never specify an encoding explicitly just call the function that defaults to the type of encoding you want.

Form Components

Forms generally consist primarily of special elements that enable the user to interact with the form, such as buttons, lists, or text-input fields. These elements often are interspersed with static text or HTML markup. For example, it s often useful to display a text caption such as "Your name:" next to an input field to indicate what should be entered into the field. HTML markup can be used to control layout of the form elements; techniques range from inserting <br> tags to force line breaks between elements to placing elements within an HTML table to achieve a particular spatial configuration.

Interactive form elements can be grouped into several categories:

  • Form-submission elements

  • Text-input elements

  • File-upload elements

  • Hidden field elements

  • Multiple-choice elements

The following sections discuss the particular HTML structure of these element types and show how to generate them using CGI.pm functions, but most elements have several things in common. Every form element begins with some tag, which includes one or more attributes, each written in attrname=attrvalue format. The most common attributes are name and value. These identify the element and specify its default value (that is, the value it has when the form is displayed initially). For example, a text-input field named telephone with initial contents of 555-1212 might be written like this:

 <input type="text" name="telephone" value="555-1212"> 

When you generate a form element by calling a CGI.pm function, it s important to specify the name and value attributes by passing like-named parameters to the function. For example, the preceding <input> tag would be produced by calling textfield() like this:[1]

[1] Actually, if you examine the output of the print statement, you ll see that it looks like this if you have CGI.pm 2.69 or higher:

 <input type="text" name="telephone" value="555-1212" /> 

Why the extra slash at the end of the tag? That s an XHTML convention. XHTML is a transition step between HTML and XML; the slash is evidence of the current trend toward an XML-enabled Web. XML is a markup language that has some similarities to HTML, but has stricter rules. One of these rules is that every opening tag <xxx > must have a corresponding closing tag </xxx >. If there is no text between the opening and closing tags, a single-tag shortcut of <xxx /> is allowed to serve as both the opening and closing tag. XHTML shares the property with XML that closing tags are required, and CGI.pm produces XHTML-compliant tags by default, which is why you get the extra slash. If you want to generate plain HTML tags, specify -no_xhtml in your use CGI statement. For example:

 use CGI qw(-no_xhtml :standard); 
 print textfield (-name => "telephone", -value => "555-1212"); 

Another common parameter to CGI.pm functions is override. This doesn t correspond to an attribute of the HTML generated by CGI.pm. Rather, it s used to control CGI.pm s sticky form behavior, which works as follows: When you generate a form element, CGI.pm looks for the element s value in two places. One is the value parameter in the function call. The other is the CGI environment. (The environment won t have any value for the element when your script is invoked initially, but it will when the user fills in the element and submits the form.) By default, any value present in the CGI environment takes precedence, even if you include a value parameter in the function call that generates the element. CGI.pm does this to make it easier for an application to generate a form that contains whatever values the user submitted in the previous form. This is useful behavior, for example, if a user fills in some but not all of the required fields in a form: You can print an error message and redisplay the form with all the information the user did provide. For situations in which this sticky behavior is undesirable, you can specify -override => 1 in the parameter list of the element-generating call to force CGI.pm to ignore the CGI environment and use the value parameter for the element s value.

To examine the environment yourself, call CGI.pm s param() function. Pass it the name of a field, and it returns the value of that field:

 $val = param ("telephone"); 

This is how a script finds out what information is present in a form that has been submitted. We ll cover param() in more detail in the later section Recovering Values of Form Elements.

Form Submission Elements

Most forms provide a button for sending the contents of the form to the Web server. Typically this button is labeled Submit, Send, Continue, or something similar. These buttons are created using <input> tags that have a type attribute of submit. To present a submission button named choice and labeled Done, for instance, the HTML looks like this:

 <input type="submit" name="choice" value="Done"> 

The label displayed in the button is controlled by the value attribute; if there is no such attribute, the default label is the button s name. The label also becomes the element s value when the user selects the button. To generate a form-submission button using CGI.pm, call the submit() function:

 print submit (-name => "choice", -value => "Done"); 

Another kind of button is a reset button, which causes form elements to revert to the values they had when the browser first displayed the form. It can be written like this:

 <input type="reset" value="Reset Form"> 

The corresponding CGI.pm call is reset(), which takes a single argument indicating the text to be displayed in the button:

 print reset ("Reset Form"); 

You do not have to specify an element name for reset buttons; if a user selects such a button, the reset action is handled entirely by the browser without transmitting anything to the Web server.

To display an image that acts as a form-submission button (thus making the image clickable ), use an <input> tag that specifies the image location, such as the following one:

 <input type="image" name="my_img" src="/books/2/307/1/html/2//images/my_img.gif" attributes...> 

The attributes for an image button should include at least name to identify the button and src to specify the image URL. Another useful attribute is alt, which provides text for the browser to display if the image cannot be found or if the user has image loading turned off. (If you re thinking that src and alt seem familiar, you re right. They are attributes commonly used in <img> tags for displaying images. You can also include other <img> tag attributes in an image button, such as height, width, or align.) To generate an image button using CGI.pm, call image_button() :

 print image_button (-name => "my_img",                      -src => "/images/my_img.gif",                      -alt => "[click me to submit]"); 

When a user selects an image button, the x and y coordinates of the image are sent to the Web server and can be recovered using param(). For a button name of my_img, the parameter names will be my_img.x and my_img.y. These coordinates enable you to respond to button clicks differently depending on where they occur (if you want to).

Should You Include a Form-Submission Element?

Sometimes you don t need to include a submission button. Browsers often will submit a form if you just press the Return or Enter key. Generally, however, it s less confusing to users if there is an explicit submission element that they can select. Another problem is that if you have multiple forms in a page, Return or Enter may do nothing or may even submit the wrong form! Also, be cautious about having multiple forms that share submission element names. (For example, you might have a button named submit in each form.) You need some way to determine which form was submitted. One way to do so is to make sure each button has a unique label. Another is to include a hidden field in each form, each having the same name but a unique value. The value of this field tells you which form was submitted.

Text-Input Elements

Text fields enable users to enter arbitrary text. They re useful for capturing input when you have no reasonable means of providing a fixed set of alternatives. If a user is ordering a shirt, you can provide pop-up menus listing all the sizes and colors in which the shirt is available. If you want to know the user s name or telephone number, however, a pop up is no good; you must provide a text field that enables the user to enter the correct value.

Text fields come in three types: single-line fields, password fields, and multiple-line fields.These are written using HTML as follows:

 <input type="text" attributes...>  <input type="password" attributes...>  <textarea attributes...>...</textarea> 

<input> elements of the text and password types both are single-line fields, so the following remarks about text fields apply also to password fields. The only difference between them is that when you type into a password field, the browser displays bullets or asterisks, not the characters you re really typing.

Text fields take the usual name and value attributes. Any value given becomes the text displayed in the element as its initial contents; otherwise, it comes up blank. You can also specify a size attribute to control the length of the field (in characters), and a maxlength attribute to limit the number of characters that a user can enter into the field. For example, you might specify a maxlength value of 2 for a field in which you want users to enter a two-character state abbreviation:

 <input type="text" name="state" size="2" maxlength="2"> 

You might also use maxlength if you re paranoid that some jerk will try to paste a 10MB core dump file into your form and submit it to see whether your Web server crashes. Unfortunately, anyone who wants to do that probably knows how to subvert your form to remove the maxlength parameter. So you should consider maxlength as advisory only, and applicable primarily to well-behaved users.

To produce a multiple-line text-input field, use <textarea>. You must also supply a closing </textarea> tag; any text between the tags displays as the field s initial contents. (This differs from the way you specify the initial value for other elements using a value attribute.) Other useful <textarea> attributes besides name are rows and cols to indicate the size of the field (both are required), and wrap to control word-wrap behavior. Allowable wrap values are off (no word wrapping), virtual (the browser performs word wrap but does not transmit line endings), and physical (the browser displays and transmits text exactly as it was typed by the user). soft and hard are synonyms for virtual and physical.

To generate text-input elements using CGI.pm calls, use the textfield(), password_field(), and textarea() functions. Here are some examples:

 print textfield (-name => "age",                      -size => 10,                      -maxlength => 10);  print password_field (-name => "password");  print textarea (-name => "comment",                  -value => "ENTER COMMENT HERE",                  -rows => 5,                  -cols => 80,                  -wrap => "virtual"); 
File-Upload Elements

To enable a user to select a file and upload it to the Web server when the form is submitted, use a file-upload field:

 <input type="file" attributes...> 

The browser will display a text-input field and a Browse button for browsing the local client s file system. Allowable attributes are name, size, and maxlength (with the same meaning as for single-line text input fields). The corresponding CGI.pm call is filefield(), which is just like textfield() except that no value parameter is accepted. (CGI.pm does this to discourage you from doing the naughty thing of initializing the field to the name of a file likely to contain sensitive information in hopes that the user will upload it accidentally.)

 print filefield (-name => "upload", -size => 60); 

When you include a file-upload element in a form, you must use an encoding type of $CGI::MULTIPART. The easiest way to do this is to generate the form by calling start_multipart_form() rather than start_form().

There are security dangers inherent to the use of file-upload fields. These dangers and some precautions you can observe to minimize them are discussed in Chapter 9, Security and Privacy Issues.

Hidden Field Elements

Hidden fields enable you to specify form elements that have a name and value and that are returned to the Web server when the user submits the form, but that are not displayed to the user. The HTML for a hidden field looks like this:

 <input type="hidden" attributes...> 

A hidden field should have at least a name attribute so that you can identify it to obtain its value when the form is processed. Normally, you ll also include a value attribute, although it s possible for the value to be empty and still be meaningful.

To generate a hidden field using CGI.pm, call the hidden() function:

 print hidden (-name => "id", -value => "34"); 

You can assign multiple values to a hidden field; just specify the value parameter as a reference to an array:

 print hidden (-name => "rgb", -value => ["red", "green", "blue"]); 

Alternatively:

 @values = ("red", "green", "blue");  print hidden (-name => "rgb," -value => \@values); 

Hidden fields are useful for passing information back and forth between your script and the client s browser because they allow one invocation of your script to communicate with the next. This enables you to tie together multiple pages. For example, we used this technique for the item-editing feature of the To-Do list manager in Chapter 2 to allow the application to track the ID of the item being edited. One invocation of the script generates the page with the form containing the item to be edited. The next invocation receives the item ID along with the item contents and uses the ID to figure out which record to update in the todo table.

Regardless of how useful hidden fields are, you shouldn t be lulled into supposing that they provide the slightest measure of security. The values are hidden only with respect to the browser s display window. The user can expose any hidden field values easily using the browser s View Source command to examine the raw HTML for your form. That s not to say you should never use hidden fields, just that you shouldn t use them for applications where security is paramount. See Chapter 9 for more discussion on how hidden fields can be exploited by hackers and for alternatives that provide better security.

Multiple-Choice Elements

Multiple-choice elements provide a group or list consisting of a fixed set of alternatives from which you can choose. Some of these are single-pick elements enabling you to select only one item from the group, such as radio button sets, pop-up menus, and scrolling lists. Others elements are multiple-pick, enabling you to select any or all (or perhaps even none) of the available choices. Multiple-pick elements include check box sets and scrolling lists. (Scrolling lists are listed for both categories because you can use them either way, to allow a single choice or multiple choices.)

Radio buttons and check boxes usually are implemented using groups consisting of multiple elements. The following HTML illustrates how to write a two-element radio button group and a three-element check box group:

 <input type="radio" name="yesno" value="yes">Yes!  <input type="radio" name="yesno" value="no" checked>No!  <input type="checkbox" name="accessories" value="floppy">Floppy disk drive  <input type="checkbox" name="accessories" value="sound">Sound card  <input type="checkbox" name="accessories" value="pad">Mouse pad 

For radio buttons, all elements within the group must have the same name. Otherwise, browsers will treat them as belonging to different groups and will enable the user to select more than one of the buttons. However, each button within a group should have a unique value so that you can distinguish which one the user selected. When the form is submitted, the value of the selected button is returned to the Web server. For the yesno group just shown, this value will be either yes or no. You can use the checked attribute to mark a button as the one to be selected by default when the browser first displays the form. (In the preceding example, the No! item is the default.)

For checkbox groups, it s not strictly necessary that you give all boxes within a group the same name, but it is more convenient. If you give each one a different name, you ll have to make several tests when the form is submitted to determine which ones are turned on. If you give all check boxes in a group the same name, CGI.pm can return to you in a single operation the values of all those that are selected. To obtain an array containing the values of all selected check boxes in the preceding accessories check box list, call param() in an array context like this:

 @accessories = param ("accessories"); 

The default value for a check box if you don t specify one is on ; clearly you should give each check box in a group a unique value if you expect to be able to tell them apart. Otherwise, you ll be left in the position of trying to discern which on value came from which check box an impossible task.

To generate a radio button set with CGI.pm, use radio_group() :

 print radio_group (-name => "yesno",                      -values => ["yes", "no"],                      -labels => {"yes" => "Yes!", "no" => "No!"}); 

The name parameter is a single string; CGI.pm automatically assigns each button in the group the same name. values is a reference to an array that provides the values for successive buttons within the group. labels is a reference to a hash that maps button values onto the captions to be displayed with each button. (If you don t specify any labels, CGI.pm uses the values as the labels.) The radio_button() call just shown indicates the label hash directly in the parameter list. You can also set up the hash beforehand like this:

 %yesno_labels = ("yes" => "Yes!", "no" => "No!");  print radio_group (-name => "yesno",                      -values => ["yes", "no"],                      -labels => \%yesno_labels); 

By default, the first radio button in a group will be selected. (That is, CGI.pm adds the checked attribute to the HTML for that button.) To select a particular button explicitly, pass a default parameter that specifies the value of the appropriate button. This call selects the no button:

 %yesno_labels = ("yes" => "Yes!", "no" => "No!");  print radio_group (-name => "yesno",                     -values => ["yes", "no"],                     -labels => \%yesno_labels,                     -default => "no"); 

To prevent any button from becoming the default, pass a default parameter listing a value that doesn t appear in the values array. (The value must be non-empty; the empty string or undef do not suppress selection of a default button.) For example, you could select no default by writing the default parameter in the previous example as follows, because [NO DEFAULT] is not the value of any of the buttons:

 -default => "[NO DEFAULT]" 

Why might you not want a default button? One situation where this is useful is for conducting an online poll. If you present the form with one of the alternatives already selected, you might bias the results toward that choice.

Generating check boxes is similar to generating radio buttons, except that you call checkbox_group() rather than radio_group():

 %acc_labels = (             "floppy" => "Floppy disk drive",              "sound" => "Sound card",              "pad" => "Mouse pad"            );  print checkbox_group (-name => "accessories",                        -values => ["floppy", "sound", "pad"],                        -labels => \%acc_labels); 

The name, values, and labels parameters are used the same way for checkbox_group() as for radio_group(), but the behavior for default buttons is different. Unlike radio button sets, where the first button is selected by default, no check box is turned on unless you specify explicitly that you want it on. Therefore, in the preceding example, none of the check boxes is selected by default. The next example causes the sound check box to be selected:

 print checkbox_group (-name => "accessories",                        -values => ["floppy", "sound", "pad"],                        -labels => \%acc_labels,                        -default => "sound"); 

To select multiple check boxes in a group, use the default parameter to pass a reference to an array of values. The following example selects both the floppy and pad buttons:

 print checkbox_group (-name => "accessories",                        -values => ["floppy", "sound", "pad"],                        -labels => \%acc_labels,                        -default => ["floppy", "pad"]); 

Radio buttons always should be created in groups of two or more, but it sometimes makes sense for a check box group to consist of a single element. This is appropriate when you just want to present a yes/no or on/off item such as Are you satisfied with our service? or With or without fries? or Check here if you wish to receive new product announcements. To generate a single check box, call checkbox() :

 print checkbox (-name => "happy",                  -value => "yes",                  -label => "Are you happy?",                  -checked => 1); 

In this call, the checked parameter causes the check box to be selected by default. Omit that parameter to leave the check box turned off.

radio_group() and checkbox_group() both accept other parameters that you may find useful. The linebreak parameter forces a line break between buttons, causing them to stack vertically. Alternatively, you can place buttons within an HTML table to arrange them nicely. If either or both of the rows and cols parameters are specified, they are taken as table dimensions. (If you specify only one of these parameters, the other defaults to 1.) When you place radio buttons or check boxes within a table, several other options become useful. You can use rowheaders and colheaders to specify labels for rows and columns. Each parameter should be passed as a reference to an array containing the appropriate number of header strings. If the headers supply all the labeling that you need, you can suppress display of any labels next to the buttons themselves by passing the nolabels parameter.

Here s a full-blown example that places a set of radio buttons within a 3 2 table, complete with headings. It enables the user to select a combination of size and color. In this case, the headings provide sufficient labeling, so a nolabels parameter is included to turn the labels off.

 print radio_group (-name => "size_color",                     -values => # column 1 values, then column 2 values                          ["small_black", "medium_black", "large_black",                          "small_white", "medium_white", "large_white"],                     -cols => 2,                     -rows => 3,                     -colheaders => ["Black", "White"],                     -rowheaders => ["Small", "Medium", "Large"],                     -nolabels => 1); 

Radio button and check box groups display a set of items using one form element per item. You can also create list elements, which present a set of items using a single form field. List elements include pop-up menus and scrolling lists. Both have an HTML syntax that uses <select> and </select> tags to enclose <option> tags that specify the items in the list. Here is an example pop-up menu that presents a list of animals from which to choose:

 <select name="animal">  <option value="dog">dog</option>  <option value="cat">cat</option>  <option value="turkey">turkey</option>  <option value="snake">snake</option>  <option value="mouse">mouse</option>  </select> 

To turn this into a scrolling list, add a size attribute to the <select> tag; the value indicates the number of rows to display in the list. (If the list contains more elements than that, the browser will display a scrollbar enabling users to move through the list.) If you want users to be able to select multiple items from the scrolling list, add the multiple attribute as well:

 <select name="animal" size="3" multiple>  <option value="dog">dog</option>  <option value="cat">cat</option>  <option value="turkey">turkey</option>  <option value="snake">snake</option>  <option value="mouse">mouse</option>  </select> 

To generate a pop-up menu using CGI.pm, call popup_menu() :

 print popup_menu (-name => "animal",                    -values => ["dog", "cat", "turkey", "snake", "mouse"]); 

By default, the item values are used as the labels to be displayed to the user. (The labels are the strings between pairs of <option> and </option> tags.) To specify your own labels, pass a reference to a hash that maps values to labels. You can also specify which item is displayed as the default. (Normally, the first item is used.) The following call uses the same values as in the preceding example, but displays animal sounds as the captions and uses the turkey item as the default:

 %animal_sounds = (             "dog" => "Bow wow",              "cat" => "Meow",              "turkey" => "Gobble, gobble",              "snake" => "Hissss",              "mouse" => "Squeak"         );  print popup_menu (-name => "animal",                    -values => ["dog", "cat", "turkey", "snake", "mouse"],                    -labels => \%animal_sounds,                    -default => "turkey"); 

To generate a scrolling list, use scrolling_list(). This function takes the same parameters as popup_menu(), but also accepts size and multiple parameters, enabling you to set the display size and to indicate that the list allows multiple selections. In addition, you can specify multiple default values if you want more than one item to be selected when the list first displays. To do this, pass a default parameter as a reference to an array of values. The following example displays the animal sound list as a multiple-pick list with three items visible, with the cat and mouse items selected as the initial defaults:

 print scrolling_list (-name => "animal",                        -values => ["dog", "cat", "turkey", "snake", "mouse"],                        -labels => \%animal_sounds,                        -size => 3,                        -multiple => 1,                        -default => ["cat", "mouse"]); 
Recovering Values of Form Elements

The preceding sections describe the CGI.pm functions you can call to generate form elements. Of course, creating a form for display is only part of the story. You ll want to process its contents after the user fills it in and submits it. The most convenient way to obtain this information is by calling CGI.pm s param() function, which examines the CGI environment and returns the values of form elements. param() can be invoked several ways:

  • If you call param() with the name of a parameter as the argument, it returns the value of that parameter:

     $val = param ("telephone"); 

    If the element is not present in the environment, param() returns undef. (Note that a parameter may be present but have an empty value if the user left it empty. This means you ll often need to check not only that a value is defined but also that it has a non-empty value.)

  • For elements that might have multiple values (such as a set of check boxes for which more than one box is checked), param() can return all the values. Just call it in an array context:

     @val = param ("animal"); 
  • If an element has multiple values but you call param() in a scalar context, it returns just the first value. This is an important difference from many list-valued Perl functions that return a count of the number of elements in the list if called in scalar context. If you want the count instead, you can do this:

     @val = param ("animal");  $count = @val; 
  • To get a list containing the names of the parameters that are present in a submitted form, call param() with no argument:

     @names = param (); 

Be aware that you cannot assume that this list names all the elements in the form. Browsers may send back values only for non-empty elements. If you don t select any members of a group of check boxes, for example, the browser won t return any value for the group. This has a very important implication: You cannot deduce what fields a form contains from the submitted form contents; you must know in advance what they are. Suppose you call param() to get a list of field names and run a loop using the names so that you can verify their values. If one goal of your verification process is to test whether fields that are required to have a value do in fact have one, the loop won t help you achieve that goal, because the list of names might not contain all fields in the form.

You can also use param() to assign values to form elements:

 param (-name => "comment", -value => "Enter your comment here");  param (-name => "animals", -value => ["chicken", "horse", "cow"]); 

If you issue these calls and then generate a form that contains elements named comment and animals, those elements will be set to the assigned values (unless you specify -override => 1 when you generate them, of course).

The ability to set form parameters this way can also be advantageous in situations where you want to process values in stages without creating global variables to store them. For example, you can call param() to extract a parameter into a temporary variable, perform some processing on it, and then call param() again to store the variable s resulting value back into the environment. When you need to refer to the value again later, extract it again. The electronic greeting card application developed in Chapter 5 is one example that demonstrates how to use this technique.

Displaying Text in Forms

Forms need not consist entirely of interactive elements that enable users to enter information and select items. You can display static text as well to enhance the appearance of your form. For example, the following code generates a form that includes a caption indicating what to enter into the text box. Without the caption, users would have no idea what to enter into the box:

 print start_form (-action => url ()),          p ("Please enter your name:"),          textfield (-name => "name"),          submit (-name => "choice", -value => "Submit"),          end_form (); 

When you mix text and form elements this way, be aware that CGI.pm performs HTML escaping for you, but only for calls specifically related to form generation. This means that for calls such as submit() or popup_menu(), you can pass strings containing characters that are special in HTML ( < , > , & , and " ), and they will be converted to the proper HTML entities (<, >, &, and &quot;). If these characters occur in arguments to other calls such as p() or td(), however, you must escape them yourself. You can do this by calling escapeHTML() :

 print start_form (-action => url ()),          p (CGI::escapeHTML ("Please enter your first & last name:")),          textfield (-name => "name"),          submit (-name => "choice", -value => "Submit"),          end_form (); 

In this example, I wrote the function as CGI::escapeHTML() because its name is not imported into your script s namespace unless you do so explicitly. If you want to invoke escapeHTML() without referring to it through the CGI:: prefix, list its name in your use CGI statement. For example:

 use CGI qw(:standard escapeHTML);  print start_form (-action => url ()),          p (escapeHTML ("Please enter your first & last name:")),          textfield (-name => "name"),          submit (-name => "choice", -value => "Submit"),          end_form (); 

Including HTML Markup in Forms

Sometimes it s useful to include HTML markup in a form to affect the appearance or layout of text or form elements. The following example uses strong() to emphasize the form title, and an HTML table to organize element captions and fields so that they line up nicely. Without using a table, the left edges of the text fields won t line up and will as a result appear ragged.

 print start_form (-action => url ()),          p (strong (escapeHTML ("Please enter your first & last name:"))),          table (             Tr (                 td ("First name:"),                  td (textfield (-name => "first_name")),              ),              Tr (                 td ("Last name:"), 
                 td (textfield (-name => "last_name")),              ),          ),          submit (-name => "choice", -value => "Submit"),          end_form (); 

In this example, it s important to call escapeHTML() to perform character escaping on the title before calling strong(). If you call strong() to emphasize the title first, and then pass the result to escapeHTML(), you ll end up escaping the special characters in the <strong> tags, with the result that those tags will display literally in the browser window!

URL Encoding

The <form> tag includes a URL as the value of the action attribute, and URLs have their own special characters, just like HTML text. If you want to use any of these characters literally, you ll need to perform some encoding to avoid generating a malformed URL. Suppose you re generating a form that is processed by a script, my script.pl, that has a space in its name:

 print start_form (-action => "my script.pl"); 

When you submit the resulting form from your browser, you may get an error such as this:

 The requested URL /cgi-perl/my was not found on this server. 

Note that everything in the script name to the right of the space has been lost. This happens because literal spaces are not legal in URLs and must be encoded. However, URL values are encoded differently than regular HTML, because the set of special characters differs. (It includes not only a space, but : , / , ? , ; , and others.) To accomplish this, use the escape() function. It is similar to escapeHTML(), but performs URL encoding rather than HTML encoding:

 print start_form (-action => escape ("my script.pl")); 

That s a somewhat unusual case, because script names normally don t include spaces. However, URL encoding also applies to other values that are used as hyperlinks, such as the href attribute of <a> tags and the src attribute of <img> tags. These values often contain parameters, and it s quite common for parameter values to require encoding. Suppose you want to generate a link that automatically triggers a search for low-priced office chairs, using an item parameter to name the type of item and restriction to indicate any special search restrictions. You might try writing the link like this:

 $url = "search.pl?item=office chair;restriction=price<100";  print a ({-href => $url}, "Search for economy office chairs"); 

That won t work: spaces cannot be used in URLs, and the < character is special. The resulting output looks like this:

 <a href="search.pl?item=office chair;restriction=price<100">  Search for economy office chairs</a> 

The a() function performs HTML encoding on the href value, which takes care of the < character in the price<100 part. But that s not good enough because it leaves the space unchanged. To generate the URL properly, use escape() :

 $url = sprintf ("search.pl?item=%s;restriction=%s",                              escape ("office chair"),                              escape ("price<100"));  print a ({-href => $url}, "Search for economy office chairs"); 

escape() encodes each special character as a % followed by two hexadecimal digits representing the character s ASCII value. The resulting hyperlink looks like this:

 <a href="search.pl?item=office%20chair;restriction=price%3C100">  Search for economy office chairs</a> 

Note that you do not want to pass the entire URL to escape() because that turns off the special meaning of characters that should remain special. Don t use escape() this way:

 $url = escape ("search.pl?item=office chair;restriction=price<100");  print a ({-href => $url}, "Search for economy office chairs"); 

That encodes the space and < characters. But it also encodes ? and ; characters that are supposed to indicate where the URL parameters are. The result is that those characters lose their special meaning:

 <a href="search.pl%3Fitem%3Doffice%20chair%3Brestriction%3Dprice%3C100">  Search for economy office chairs</a> 

Like escapeHTML(), escape() must be imported into your script s namespace with the useCGI statement if you want to refer to it without a leading CGI:: prefix:

 use CGI qw(:standard escapeHTML escape); 

URL Shortcuts

If you write a script that generates a page containing links to other pages, it s always correct to write the links using an absolute URL that includes the host name and full pathname to the page:

 <a href="http://www.snake.net/cgi-perl/somescript.pl">A script</a>  <a href="http://www.snake.net/projects/index.html">Project index</a> 

However, it s often possible to use shortcuts by providing relative URLs. If you re referring to a page that is located on the same server, you can omit the initial part of the URL up through the host name:

 <a href="/cgi-perl/somescript.pl">A script</a>  <a href="/projects/index.html">Project index</a> 

Furthermore, if you re referring to a page located in the same directory as your script, you can even leave out the pathname leading to the page. If two links are generated by a script installed in the cgi-perl directory, for example, the link for somescript.pl need not include the leading path because it s in the same directory. index.html is not located there, so we still need the path. Therefore, the minimal URLs we can use are as follows:

 <a href="somescript.pl">A script</a>  <a href="/projects/index.html">Project index</a> 

URL References and Mirror Hosts

Be careful when using URL shortcuts if some of your pages are mirrored (replicated) onto another host but contain links to pages that are not mirrored. You should refer to the non-mirrored pages using absolute URLs. If you use relative links, when someone visits the mirror host and clicks a link to a non-mirrored page, the browser will look for that page on the mirror host and an error will result.

A related issue concerning security occurs if you re mirroring a secure page that is accessed using absolute URLs beginning with the https prefix rather than http. If you reference embedded content (such as images) from a secure page, be sure that their URLs also begin with https or the referencing page will become insecure.

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