Defining Forms and Processing Form Data

   

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 3.  The Guestbook CGI Application


The guestbook.cgi script only generates output. The other half of CGI deals with input from the user. Input is more complex for two reasons. First, we have to define another HTML page that has a form for the user to fill out. Second, the data from the form is organized and encoded in a standard form that must be decoded by the script. Example 3-8 on page 40 defines a very simple form, and the procedure that decodes the form data is shown in Example 11-6 on page 155.

The guestbook page contains a link to newguest.html. This page contains a form that lets a user register his or her name, home page URL, and some additional HTML markup. The form has a submit button. When a user clicks that button in their browser, the information from the form is passed to the newguest.cgi script. This script updates the database and computes another page for the user that acknowledges the user's contribution.

The newguest.html Form

An HTML form contains tags that define data entry fields, buttons, checkboxes, and other elements that let the user specify values. For example, a one-line entry field that is used to enter the home page URL is defined like this:

 <INPUT TYPE=text NAME=url> 

The INPUT tag is used to define several kinds of input elements, and its type parameter indicates what kind. In this case, TYPE=text creates a one-line text entry field. The submit button is defined with an INPUT tag that has TYPE=submit, and the VALUE parameter becomes the text that appears on the button:

 <INPUT TYPE=submit NAME=submit VALUE=Register> 

A general type-in window is defined with the TEXTAREA tag. This creates a multiline, scrolling text field that is useful for specifying lots of information, such as a free-form comment. In our case we will let guests type in HTML that will appear with their guestbook entry. The text between the open and close TEXTAREA tags is inserted into the type-in window when the page is first displayed.

 <TEXTAREA NAME=markup ROWS=10 COLS=50>Hello.</TEXTAREA> 

A common parameter to the form tags is NAME=something. This name identifies the data that will come back from the form. The tags also have parameters that affect their display, such as the label on the submit button and the size of the text area. Those details are not important for our example. The complete form is shown in Example 3-8:

Example 3-8 The newguest.html form.
 <!Doctype HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <HTML> <HEAD> <TITLE>Register in my Guestbook</TITLE> <!-- Author: bwelch --> <META HTTP-Equiv=Editor Content="SunLabs WebTk 1.0beta 10/11/96"> </HEAD> <BODY> <FORM ACTION="newguest.cgi" METHOD="POST"> <H1>Register in my Guestbook</H1> <UL> <LI>Name <INPUT TYPE="text" NAME="name" SIZE="40"> <LI>URL  <INPUT TYPE="text" NAME="url" SIZE="40"> <P> If you don't have a home page, you can use an email URL like "mailto:welch@acm.org" <LI>Additional HTML to include after your link: <BR> <TEXTAREA NAME="html" COLS="60" ROWS="15"> </TEXTAREA> <LI><INPUT TYPE="submit" NAME="new" VALUE="Add me to your guestbook"> <LI><INPUT TYPE="submit" NAME="update" VALUE="Update my guestbook entry"> </UL> </FORM> </BODY> </HTML> 

The newguest.cgi Script

When the user clicks the Submit button in their browser, the data from the form is passed to the program identified by the Action parameter of the form tag. That program takes the data, does something useful with it, and then returns a new page for the browser to display. In our case the FORM tag names newguest.cgi as the program to handle the data:

 <FORM ACTION=newguest.cgi METHOD=POST> 

The CGI specification defines how the data from the form is passed to the program. The data is encoded and organized so that the program can figure out the values the user specified for each form element. The encoding is handled rather nicely with some regular expression tricks that are done in Cgi_Parse. Cgi_Parse saves the form data, and Cgi_Value gets a form value in the script. These procedures are described in Example 11-6 on page 155. Example 3-9 starts out by calling Cgi_Parse:

Example 3-9 The newguest.cgi script.
 #!/bin/sh # \ exec tclsh "$0" ${1+"$@"} # source cgilib.tcl from the same directory as newguest.cgi set dir [file dirname [info script]] source [file join $dir cgilib.tcl] set datafile [file join $dir guestbook.data] Cgi_Parse # Open the datafile in append mode if [catch {open $datafile a}out] {    Cgi_Header "Guestbook Registration Error" \        {BGCOLOR=black TEXT=red}    P    puts "Cannot open the data file"    P    puts $out;# the error message    exit 0 } # Append a Tcl set command that defines the guest's entry puts $out "" puts $out [list set Guestbook([Cgi_Value name]) \     [list [Cgi_Value url] [Cgi_Value html]]] close $out # Return a page to the browser Cgi_Header "Guestbook Registration Confirmed" \     {BGCOLOR=white TEXT=black} puts " <DL> <DT>Name <DD>[Cgi_Value name] <DT>URL <DD>[Link [Cgi_Value url] [Cgi_Value url]] </DL> [Cgi_Value html] " Cgi_End 

The main idea of the newguest.cgi script is that it saves the data to a file as a Tcl command that defines an element of the Guestbook array. This lets the guestbook.cgi script simply load the data by using the Tcl source command. This trick of storing data as a Tcl script saves us from the chore of defining a new file format and writing code to parse it. Instead, we can rely on the well-tuned Tcl implementation to do the hard work for us efficiently.

The script opens the datafile in append mode so that it can add a new record to the end. Opening files is described in detail on page 110. The script uses a catch command to guard against errors. If an error occurs, a page explaining the error is returned to the user. Working with files is one of the most common sources of errors (permission denied, disk full, file-not-found, and so on), so I always open the file inside a catch statement:

 if [catch {open $datafile a} out] {     # an error occurred } else {     # open was ok } 

In this command, the variable out gets the result of the open command, which is either a file descriptor or an error message. This style of using catch is described in detail in Example 6-14 on page 77.

The script writes the data as a Tcl set command. The list command is used to format the data properly:

 puts $out [list set Guestbook([Cgi_Value name]) \      [list [Cgi_Value url] [Cgi_Value html]]] 

There are two lists. First the url and html values are formatted into one list. This list will be the value of the array element. Then, the whole Tcl command is formed as a list. In simplified form, the command is generated from this:

 list set variable value 

Using the list command ensures that the result will always be a valid Tcl command that sets the variable to the given value. The list command is described in more detail on page 61.


       
    Top
     



    Practical Programming in Tcl and Tk
    Practical Programming in Tcl and Tk (4th Edition)
    ISBN: 0130385603
    EAN: 2147483647
    Year: 1999
    Pages: 478

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