The guestbook.cgi Script

   

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

Table of Contents
Chapter 3.  The Guestbook CGI Application


The guestbook.cgi Script

The guestbook.cgi script computes a page that lists all the registered guests. The example is shown first, and then each part of it is discussed in more detail later. One thing to note right away is that the HTML tags are generated by procedures that hide the details of the HTML syntax. The first lines of the script use the UNIX trick to have tclsh interpret the script. This trick is described on page 26:

Example 3-3 The guestbook.cgi script.
 #!/bin/sh # guestbook.cgi # Implement a simple guestbook page. # The set of visitors is kept in a simple database. # The newguest.cgi script will update the database. # \ exec tclsh "$0" ${1+"$@"} # The cgilib.tcl file has helper procedures # The guestbook.data file has the database # Both file are in the same directory as the script set dir [file dirname [info script]] source [file join $dir cgilib.tcl] set datafile [file join $dir guestbook.data] Cgi_Header "Brent's Guestbook" {BGCOLOR=white TEXT=black} P if {![file exists $datafile]} {    puts "No registered guests, yet."    P    puts "Be the first [Link {registered guest!}newguest.html]" } else {    puts "The following folks have registered in my GuestBook."    P    puts [Link Register newguest.html]    H2 Guests    catch {source $datafile}    foreach name [lsort [array names Guestbook]] {       set item $Guestbook($name)       set homepage [lindex $item 0]       set markup [lindex $item 1]       H3 [Link $name $homepage]       puts $markup    } } Cgi_End 

Using a Script Library File

The script uses a number of Tcl procedures that make working with HTML and the CGI interface easier. These procedures are kept in the cgilib.tcl file, which is kept in the same directory as the main script. The script starts by sourcing the cgilib.tcl file so that these procedures are available. The following command determines the location of the cgilib.tcl file based on the location of the main script. The info script command returns the file name of the script. The file dirname and file join commands manipulate file names in a platform-independent way. They are described on page 102. I use this trick to avoid putting absolute file names into my scripts, which would have to be changed if the program moves later:

 set dir [file dirname [info script]] source [file join $dir cgilib.tcl] 

Beginning the HTML Page

The following command generates the standard information that comes at the beginning of an HTML page:

 Cgi_Header {Brent's GuestBook} {bgcolor=white text=black} 

The Cgi_Header is shown in Example 3-4:

Example 3-4 The Cgi_Header procedure.
 proc Cgi_Header {title {bodyparams {}}} {     puts stdout \ "Content-Type: text/html <HTML> <HEAD> <TITLE>$title</TITLE> </HEAD> <BODY $bodyparams> <H1>$title</H1>" } 

The Cgi_Header procedure takes as arguments the title for the page and some optional parameters for the HTML <Body> tag. The guestbook.cgi script specifies black text on a white background to avoid the standard gray background of most browsers. The procedure definition uses the syntax for an optional parameter, so you do not have to pass bodyparams to Cgi_Header. Default values for procedure parameters are described on page 81.

The Cgi_Header procedure just contains a single puts command that generates the standard boilerplate that appears at the beginning of the output. Note that several lines are grouped together with double quotes. Double quotes are used so that the variable references mixed into the HTML are substituted properly.

The output begins with the CGI content-type information, a blank line, and then the HTML. The HTML is divided into a head and a body part. The <TITLE> tag goes in the head section of an HTML document. Finally, browsers display the title in a different place than the rest of the page, so I always want to repeat the title as a level-one heading (i.e., H1) in the body of the page.

Simple Tags and Hypertext Links

The next thing the program does is to see whether there are any registered guests or not. The file command, which is described in detail on page 102, is used to see whether there is any data:

 if {![file exists $datafile]} { 

If the database file does not exist, a different page is displayed to encourage a registration. The page includes a hypertext link to a registration page. The newguest.html page will be described in more detail later:

 puts "No registered guests, yet." P puts "Be the first [Link {registered guest!}newguest.html]" 

The P command generates the HTML for a paragraph break. This trivial procedure saves us a few keystrokes:

 proc P {} {    puts <P> } 

The Link command formats and returns the HTML for a hypertext link. Instead of printing the HTML directly, it is returned, so you can include it in-line with other text you are printing:

Example 3-5 The Link command formats a hypertext link.
 proc Link {text url} {     return "<A HREF=\"$url\">$text</A>" } 

The output of the program would be as below if there were no data:

Example 3-6 Initial output of guestbook.cgi.
 Content-Type: text/html <HTML> <HEAD> <TITLE>Brent's Guestbook</TITLE> </HEAD> <BODY BGCOLOR=white TEXT=black> <H1>Brent's Guestbook</H1> <P> No registered guests. <P> Be the first <A HREF="newguest.html">registered guest!</A> </BODY> </HTML> 

If the database file exists, then the real work begins. We first generate a link to the registration page, and a level-two header to separate that from the guest list:

 puts [Link Register newguest.html] H2 Guests 

The H2 procedure handles the detail of including the matching close tag:

 proc H2 {string} {     puts "<H2>$string</H2>" } 

Using a Tcl Array for the Database

The datafile contains Tcl commands that define an array that holds the guestbook data. If this file is kept in the same directory as the guestbook.cgi script, then you can compute its name:

 set dir [file dirname [info script]] set datafile [file join $dir guestbook.data] 

By using Tcl commands to represent the data, we can load the data with the source command. The catch command is used to protect the script from a bad data file, which will show up as an error from the source command. Catching errors is described in detail on page 79:

 catch {source $datafile} 

The Guestbook variable is the array defined in guestbook.data. Array variables are the topic of Chapter 8. Each element of the array is defined with a Tcl command that looks like this:

 set Guestbook(key) {url markup} 

The person's name is the array index, or key. The value of the array element is a Tcl list with two elements: their URL and some additional HTML markup that they can include in the guestbook. Tcl lists are the topic of Chapter 5. The following example shows what the command looks like with real data:

 set {Guestbook(Brent Welch)} {     http://www.beedub.com/     {<img src=http://www.beedub.com/welch.gif>} } 

The spaces in the name result in additional braces to group the whole variable name and each list element. This syntax is explained on page 90. Do not worry about it now. We will see on page 42 that all the braces in the previous statement are generated automatically. The main point is that the person's name is the key, and the value is a list with two elements.

The array names command returns all the indices, or keys, in the array, and the lsort command sorts these alphabetically. The foreach command loops over the sorted list, setting the loop variable x to each key in turn:

 foreach name [lsort [array names Guestbook]] { 

Given the key, we get the value like this:

 set item $Guestbook($name) 

The two list elements are extracted with lindex, which is described on page 63.

 set homepage [lindex $item 0] set markup [lindex $item 1] 

We generate the HTML for the guestbook entry as a level-three header that contains a hypertext link to the guest's home page. We follow the link with any HTML markup text that the guest has supplied to embellish his or her entry. The H3 procedure is similar to the H2 procedure already shown, except it generates <H3> tags:

 H3 [Link $name $homepage] puts $markup 

Sample Output

The last thing the script does is call Cgi_End to output the proper closing tags. Example 3-7 shows the output of the guestbook.cgi script:

Example 3-7 Output of guestbook.cgi.
 Content-Type: text/html <HTML> <HEAD> <TITLE>Brent's Guestbook</TITLE> </HEAD> <BODY BGCOLOR=white TEXT=black> <H1>Brent's Guestbook</H1> <P> The following folks have registered in my guestbook. <P> <A HREF="newguest.html">Register</A> <H2>Guests</H2> <H3><A HREF="http://www.beedub.com/">Brent Welch</A></H3> <IMG src="/books/3/480/1/html/2/http://www.beedub.com/welch.gif"> </BODY> </HTML> 

       
    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