Professional Documents
Culture Documents
digi tal
Network Systems Laboratory 250 University Avenue Palo Alto, California 94301 USA
The Network Systems Laboratory (NSL), begun in August 1989, is a research laboratory devoted to components and tools for building and managing real-world networks. Our charter is to research and develop innovative internetworking systems. We apply what we have learned to help open strategic new markets for Digital. Our expertise is in open systems and in big networks, especially those that cross organizational boundaries. Our interest is in building real systems for real users, in order to advance the state of the art. Sometimes we work on systems inside Digital; sometimes we work directly on large revenue projects. Our strategy, since we are a small group, is to leverage our work by using, whenever we can, existing hardware and software systems. We do this by building on the large existing body of widely-accepted networking technologies. We like to work in partnership with other groups in Digital, including large account teams and engineering organizations. Our deliverables are the communication of ideas to other parts of Digital by building and releasing prototype systems, consulting within Digital, publishing technical reports, and participation in external research and standards activities. NSL is also a focal point for operating Digitals internal IP research network (CRAnet) and the Palo Alto Internet gateway. Ongoing experience with practical network operations provides an important basis for research on network management. We publish the results of our work in a variety of journals, conferences, research reports, and technical notes. This document is a technical note. We use this form for rapid distribution of technical material. Usually this represents research in progress. Research reports are normally accounts of completed research and may include material from earlier technical notes. You can order reports and technical notes by mail by sending a request to: Technical Report Distribution Digital Equipment Corporation Network Systems Laboratory - WRL-1 250 University Avenue Palo Alto, California 94301 USA You can also order reports and technical notes by electronic mail or browse them on the World Wide Web. Use one of the following addresses: Internet mail: NSL-Techreports@pa.dec.com World Wide Web (outside of Digital): http://www.research.digital.com/nsl/home.html World Wide Web (Internal): http://nsl.pa.dec.com/nsl/home.html To obtain more details on ordering by electronic mail, send a message to one of these mail addresses with the word help in the Subject line; you will receive detailed instructions.
Abstract
One of the most interesting uses of the World Wide Web is the creation of interactive applications that let users ask questions, query databases, or place orders, using HTML forms. Most of the work of developing such applications is the creation of programs to process these forms. John Ousterhouts Tool Command Language (Tcl) is an ideal tool for this task. With additional extensions, Tcl can access databases and be distributed across machines. This paper gives a brief introduction to HTML forms, how to create them, and how to process them using Tcl. We assume that the reader is familiar with the World Wide Web, the operation of Mosaic, and the Hypertext Markup Language, HTML. Copyright 2005 Hewlett-Packard Development Company, L.P.
digi tal
Network Systems Laboratory 250 University Avenue Palo Alto, California 94301 USA
i
NSL TN-14
ii
NSL TN-14
Table of Contents
1. Introduction 2. Overview and Tutorial 2.1. Introduction to HTML Forms 2.2. Query Processing Overview 2.3. A Simple Example 2.4. Protection From Abuse 2.5. Processing Forms With Shell Scripts 3. The Common Gateway Interface (CGI) 3.1. The Query 3.2. CGI Environment Variables 3.3. Script Output 4. Using Tcl to Process Forms 4.1. The Tcl Language 4.2. Tcl Extensions for CGI 4.3. A More Complex Example 5. Tcl Extensions 5.1. Existing Tcl Extensions 5.2. Building Tcl Shells 5.3. Remote Procedure Call -- Distributed Tcl Scripts 6. Building Large Applications 6.1. Maintaining State -- In the Query 6.2. Maintaining State -- In the Server 6.3. Maintaining State -- In the URL 6.4. Maintaining State -- At the End of URL 6.5. Maintaining State -- In the HTTP Header 6.6. Efficiency Concerns 7. Additional Details 7.1. Making Relative URLs Work 7.2. Hardwired Queries 7.3. The Evil Reload Button 7.4. Define a Tcl Setup Script 7.5. Check for and Log Errors 7.6. Server Security 7.7. Transaction Security 7.8. What Client is Asking? I. Building HTML Forms I.1. The FORM Tag I.2. The Submit Button I.3. The Reset Button I.4. One-Line Text Input I.5. Hidden Data I.6. Checkboxes I.7. Radio Buttons I.8. Multi-line Text Input I.9. Menus and Scrolling Lists I.10. Images 1 3 3 4 5 7 7 9 11 11 13 15 15 16 17 21 21 22 23 25 25 26 27 27 27 28 29 29 30 31 31 34 35 36 36 37 37 37 38 38 39 40 41 41 42 44
iii
NSL TN-14
iv
NSL TN-14
1. Introduction
The World Wide Web provides easy access to documents stored anywhere on the Internet. Web browsers, such as Mosaic, give a "point-and-click" interface to these documents. A recent addition to this interface is the ability to have fill-out forms, which allow users to make complex queries of a Web server. These forms make it possible to build sophisticated interactive applications, using Mosaic as a publicly-available user-interface engine. The Web interface to the Future Fantasy Bookstore is one such application. Using forms, it allows users to browse the catalog, order books, and send in comments. It is accessible at the Uniform Resource Locator (URL) http://www.commerce.digital.com/paloalto/FutureFantasy/home.html. Most of the examples in this report are drawn from our implementation of the bookstores Web "storefront". If you have access to the Web, you should take some time, now, to look at the bookstore and experiment with the browsing facilities. Please be aware that this is a real bookstore, and that any order you place will be treated as a real order. If you just avoid giving your name and address, you cant accidentally place an order. This report discusses the following topics: Chapter 2 -- Overview and Tutorial How Hypertext Markup Language (HTML) forms are constructed and used to pass data to applications. A brief tutorial example is included. Chapter 4 -- Using Tcl to Process Forms How Tcl can be used to process forms, highlights of the language, and a more extensive example. Chapter 5 -- Tcl Extensions Additional Tcl extensions that are useful for more sophisticated applications, such as database access and distributed applications. Chapter 6 -- Building Large Applications Issues relevant to building large applications using forms. Chapter 7 -- Additional Details Miscellaneous details -- useful tricks and nasty pitfalls. Appendix I -- Building HTML Forms An in-depth description of the input elements available for forms. Standards and implementations change rapidly. This report is current as of the following versions of software: X Mosaic version 2.4 Windows Mosaic version 2.0a4 Macintosh Mosaic version 1.3 NCSA httpd version 1.2 Tcl version 7.3 Most of the Tcl-related files mentioned in this report are available by anonymous FTP from nsl.pa.dec.com (Digital internal only), in the /pub/tcl directory. Outside of Digital, cgi_tcl is available from gatekeeper.dec.com in the /pub/DEC/NSL/tcl directory.
NSL TN-14
The primary repository for Tcl sources and documentation is sprite.berkeley.edu, in the /tcl directory. The master archive of Tcl extensions, as well as a mirror copy of the Tcl sources, is at harbor.ecn.purdue.edu, in the /pub/tcl directory. Tcl itself is described in Tcl and the Tk Toolkit by John Ousterhout, published by Addison-Wesley, ISBN 0-201-63337-X.
NSL TN-14
The following input elements are available in HTML forms: Single-line text input (echo or non-echo) Multiple-line text input, with scroll bars Pop-up menus Scrolling lists (single or multiple selections) Checkboxes (select zero or many options)
NSL TN-14
Radio buttons (select exactly one option) Invisible text, for holding state information. (More on this, later.) Bitmap images, for sending X,Y coordinates. Two special buttons are available: the Submit button, which sends the query to be processed, and the Reset button, which resets the form to its default state. These are evident in the example as the Submit Query and Clear the Form buttons. When the form is submitted for processing, the data from all of the elements in the form is packaged up into a query and sent to a Web server. The official reference for forms is http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fillout-forms/overview.html. Appendix I gives a tutorial on the different form elements.
NSL TN-14
When the HTTP server receives the query, it runs a program (3) which processes the query. The script output (4) is a new document, which is sent back (5) and displayed to the user.
Here is the source for the form: <FORM METHOD="POST" ACTION="cgi-bin/simple"> Type your name: <INPUT TYPE="text" NAME="username"> <P> <INPUT TYPE="submit" VALUE="send query"> </FORM> The HTML form has three components: 1. The <FORM> tag, which surrounds the entire form. It has two attributes: METHOD="POST", which makes the query be sent as a POST query, with the query contents sent as standard input, rather than as part of the URL. POST is the preferred query mechanism.
5
NSL TN-14
ACTION="cgi-bin/simple", which tells the name of the script to execute. In this case, weve given a relative URL, which means that it will look for the script cgi-bin/simple in the same directory as the current document. Section 7.1 describes some extra configuration that needs to be done to NCSA httpd to make this script get executed. 2. <INPUT TYPE="text" NAME="username">, specifies an input element for entering text. When the query is sent, the users input will be associated with the name username. 3. <INPUT TYPE="submit" VALUE="send query">, specifies the button that will submit the query for processing. The cgi-bin/simple script that executes the query extracts the users name from the query and generates a minimal HTML document as a response, confirming what the user entered. Here is the script: #! /usr/local/bin/tcl_cgi cgi_parse_query [cgi_get_query] Q puts "Content-type: text/html <TITLE>Query Response</TITLE> <H1>Query Response</H1> Your name is <B>$Q(username)</B>. <P> You sent your query from <B>$env(REMOTE_HOST)</B>." It consists of: 1. The first line tells the Unix operating system to execute the program /usr/local/bin/tcl_cgi (which is our Tcl interpreter) to run the script. This is what actually causes the script to be executed. 2. The first command uses the CGI extensions to get the query and then parse it, putting the name/value pairs into the array Q. 3. The "puts" command (which spans the rest of the script) writes the multi-line string to standard output: a. The first line of output should always be "Content-type: text/html" and should be followed by a blank line. This is the header of the HTTP response. Additional header lines are possible, but they are rarely used. b. The next two lines are the normal beginning of an HTML document: <TITLE> and <H1> header. c. $Q(username) is whatever the user typed in the input field. d. $env(REMOTE_HOST) is the value of the REMOTE_HOST environment variable, which was set by httpd to the name of the host that submitted the query. Section 3.2 lists all of the possible environment variables.
NSL TN-14
The output of the script is sent back to the Web client that made the request, which formats it and presents it to the user.
NSL TN-14
that these shells provide a very wide-open environment for interpreting (and executing) user input. Without extreme care, it is easy to accidently program a security hole into your system. There have already been reports of system break-ins, due to poorly written formprocessing shell scripts. Recall that an HTTP form query looks something like: n1=value1&n2=value2&n3=value3 When the script is started, the query must first be obtained from either standard input or an environment variable. Then, the query must be parsed, first splitting it at the ampersand characters, then breaking apart the name/value pairs, and then processing any escaped characters in the names and values. NCSA httpd comes with software to do this. Typically, a shell command must be executed to set a shell variable (corresponding to one of the names) to the corresponding value. Later on, these variables will be used to execute commands, form command arguments, etc. This is where the biggest vulnerability comes from: if shell meta characters (such as , ", \, ) are included in the input, a shell syntax error can result. At worst, a malicious (and patient) user can execute arbitrary commands from your script. A relatively minor disadvantage of shell scripts is that they tend to execute a lot of commands, which makes them significantly slower than most other solutions.
NSL TN-14
NSL TN-14
httpd
query
query script
The query will either be contained on standard input or in an environment variable, depending upon how the form was written. The Tcl CGI package described in Section 4.2 takes care of getting the query from the right place. In most situations, the scripts standard output is sent back to the user. In some cases, the script output instructs the HTTP server to perform other actions. Section 3.3 describes all of the possibilities. Except for the query, most of the information about the users request is passed to the script via environment variables, set by the HTTP server. There are over a dozen standard variables (see Section 3.2). Here are the commonly used ones: REMOTE_HOST The name of the host making the request. If the name is not available, this is not set. REMOTE_ADDR The IP address of the host making the request. HTTP_USER_AGENT (CGI version 1.1 or later) The name and version of the client program that submitted the query. For example, the current (as of this writing) version of NCSA Mosaic returns "NCSA Mosaic for the X Window System/2.4 libwww/2.12 modified".
10
NSL TN-14
HTTP_REFERER (CGI version 1.1 or later) The URL of the document from which the current URL was obtained. This is especially useful for debugging obsolete references.
11
NSL TN-14
SCRIPT_NAME PATH_INFO
The virtual name of the script being executed. This is the part of the URL after the host name, beginning with the first "/". If the script specified extra path components after the name of the script, it is put here. For example, if the script named "/cgi-bin/script" was invoked with a URL of "/cgi-bin/script/extra/stuff", this variable will contain "/extra/stuff".
PATH_TRANSLATED The server provides a translated version of PATH_INFO, which takes the path and does any virtual-to-physical mapping to it. (I dont understand what the purpose of this is.) QUERY_STRING The information after the ? in the requested URL, if any. This is how the query is passed to the script, for the GET method. REMOTE_HOST The name of the host making the request. If the name is not available, this is not set. REMOTE_ADDR The IP address of the host making the request. AUTH_TYPE If the server supports user authentication, and the script is protected, this is the protocol-specific authentication method used to validate the user.
REMOTE_USER If the server supports user authentication, and the script is protected, this is the username they have authenticated as. REMOTE_IDENT If the HTTP server supports RFC 931 identification, then this variable will be set to the remote user name retrieved from the server. Usage of this variable should be limited to logging only. CONTENT_TYPE For queries which have attached information, such as POST and PUT, this is the content type of the data. CONTENT_LENGTH The length of the content, as given by the client. If the client sends HTTP header lines that are not interpreted by the server, they are placed into the environment. For each HTTP header line, the environment variable name is formed by prefixing the header name with "HTTP_", capitalizing the name, and replacing any "-" characters with "_". For example, the content of the User-Agent: header line would be put into an environment variable named HTTP_USER_AGENT. This feature is new as of CGI version 1.1 (implemented by NCSA httpd 1.2). Here are some environment variables, derived from HTTP header lines, that may be of use. Note that these are optional, so they will not always be available. HTTP_USER_AGENT The name and version of the client program that submitted the query. For example, the current (as of this writing) version of NCSA Mosaic returns "NCSA Mosaic for the X Window System/2.4 libwww/2.12 modified". HTTP_REFERER The URL of the document from which the current URL was obtained. This is especially useful for debugging obsolete references.
12
NSL TN-14
13
NSL TN-14
14
NSL TN-14
NSL TN-14
{curly braces}
around words prevent any interpretation of the contents. They are usually used around procedure bodies, where the contents will be evaluated later. Braces are the equivalent of shell single quotes, except that they balance. cause the contents to be executed as a command, substituting the result of the command as a single word. Square brackets are the equivalent of shell back quotes, except that they balance.
[square brackets]
Tcl is a fully functional high-level language, with features for: looping (while, for, foreach) conditionals (if, case) full error handling (catch, error backtrace) procedure definition, with fixed or variable argument lists files (open/close/read/write, plus full access interrogation) subprocesses (full pipelines, plus reading/writing to/from variables) Full math expression support. Functions written in C can be added in. Besides these "ordinary" features, Tcl also has a number of other advanced capabilities: Full set of operators for operating on lists, lists-of-lists, etc. arrays are fully associative strings may be of arbitrary length regular expression matching and substitution ability to "trace" variable accesses -- execute Tcl code when a variable is read, written, or deleted. Finally, the most important feature is that Tcl can be extended with procedures written in C. All of the Tcl language features are accessible from C-language routines: command creation, deletion, and execution dynamic strings variables and arrays parsing and expression evaluation generalized hash tables process creation and control
16
NSL TN-14
list-names, those VALUEs will be appended to array(NAME) as Tcl list elements. Later on, Tcl list-processing functions can be used to take apart the list. If the -strip option is given, non-printing characters will be removed from the query VALUEs. For example, the command set query [cgi_get_query] might set query to author=Clarke&isbn=123456&isbn=987654. Then, the result of cgi_parse_query $query Q isbn would be: $Q(author) = Clarke $Q(isbn) = 123456 987654 Note that $Q(isbn) is a list containing all of the values seen in the query for the NAME isbn. Note that both of these commands can produce errors if given bad input from the Web browser. You should definitely check for errors when executing these commands (see Section 7.5). The manual page for tcl_cgi lists all of the possible errors. Tcl also provides access to environment variables through the array env. This array is read/write, meaning that changes to the array are reflected in the environment exported by Tcl. The result of putting together Tcl and this CGI library is a Tcl "shell" that can be used to interpret Tcl scripts. Those scripts have direct access to the query and the environment variables. By convention, we call the interpreter tcl_cgi. The usual way that such interpreters are used is to make the first line of the script start with "#!", followed by the name of the interpreter used to execute the script. If we put the Tcl interpreter in /usr/local/bin/tcl_cgi, then the first line of the script should be: #! /usr/local/bin/tcl_cgi Some Unix systems limit the length of the interpreter name that they will accept to about 24 characters. If the name is longer than that, the shell /bin/sh will be used, which will cause confusing (and incorrect) results. Finally, the script file must be made executable, using the chmod command.
17
NSL TN-14
Heres the HTML specification of the form: <FORM METHOD="POST" ACTION="cgi-bin/comments"> Reply address: <INPUT TYPE="text" NAME="email" SIZE=40><P> <TEXTAREA NAME="comments" ROWS=6 COLS=50></TEXTAREA><P> <INPUT TYPE="submit" VALUE="Send Comments"><P> </FORM> The script that is executed when the button is pushed is named "cgi-bin/comments", relative to the location of the HTML file containing the form. The first part of the script defines a Tcl procedure "domail" that sends a mail message. #! /usr/local/bin/tcl_cgi # This defines the "domail" procedure, which sends # a mail message, setting the "to", "cc", "reply-to" and # "subject" fields to the arguments provided, with the # body as given by the "input" argument. proc domail {to cc reply subject input} { set fid [open "|mail $to" w] puts $fid "To: $to" if {$cc != ""} { puts $fid "CC: $cc" } if {$reply != ""} { puts $fid "Reply-To: $reply" } puts $fid "Subject: $subject" puts $fid "" puts $fid $input close $fid } The rest of the script obtains and parses the query, invokes the "domail" procedure, and generates an HTML response for the user.
18
NSL TN-14
set comments "comments@bigmax" # get and parse the query cgi_parse_query [cgi_get_query] Q # send the e-mail message, using the above procedure. domail $comments $Q(email) $Q(email) \ "Comments from $env(REMOTE_HOST)" $Q(comments) puts {Content-type: text/html <TITLE>Thank You</TITLE> <H1>Thank You</H1> Your comments have been submitted.} if {$Q(email) != ""} { puts "<P>A copy has been sent to $Q(email)." }
19
NSL TN-14
20
NSL TN-14
5. Tcl Extensions
The basic tcl_cgi shell provides the basic Tcl language and the ability to use the HTTP CGI to get the query. This is often sufficient, but falls short when the query needs to interface with other systems, such as databases, on-line transaction processing systems, or other existing systems. One way to access such systems is to run whatever programs are needed using Tcls process control facilities, sending commands and data via standard input and output. This has the advantage that the existing system doesnt need to be modified, and is just "driven" by the Tcl script. This option is quite powerful and flexible, and shouldnt be overlooked. The other way to access such systems is to extend Tcl and build in capabilities to access the system. This is done by writing routines in C that communicate with the existing system, and can be invoked from Tcl as ordinary commands. This has the advantage that the system can be accessed directly from Tcl, without the overhead (and possible delay) of invoking the existing program. In addition, the Tcl commands to access the system can be tailored to the needs of the script. The disadvantage is that programming is required, although the Tcl aspects are not difficult.
21
NSL TN-14
22
NSL TN-14
int Tcl_AppInit(interp) Tcl_Interp *interp; { /* * Execute a start-up script. * This may need to be loaded before the extensions! */ if (TCL_OK != Tcl_Eval(interp, initCmd)) return TCL_ERROR; /* * Calls to init procedures for various extensions. */ if (TCL_OK != Sql_Init(interp)) return TCL_ERROR; if (TCL_OK != Cgi_Init(interp)) return TCL_ERROR; return TCL_OK; } In the Makefile, the final cc line would look something like: cc -o tcl_sql_cgi tclAppInit.c -ltcl -ltcl_sql -ltcl_cgi -lm
23
NSL TN-14
CGI query
httpd
returned document
query script
Remote Procedure Call
application server
Note that the application server, does not have to be on the same host as the HTTP daemon and Tcl script. If needed, the application server can be replicated. For distributed operation, two different Tcl shells are needed, one for the client (invoked by httpd) and the other for the application server (which runs all the time). The client needs the CGI, DP, and Tk-X extensions. The server needs DP, Tk-X, and any extensions needed for the application (e.g., SQL). During operation, the server executes the dp_MakeRPCServer command, which listens on a specified TCP/IP port. Options can be specified to restrict which hosts may issue RPC calls, and to restrict what Tcl commands may be executed. Typically, the client and server will agree on a common interface, implemented by a set of purpose-built Tcl commands. After that point, the server just waits for RPC requests to arrive. When a client starts up, it first establishes a connection to the server, using the dp_MakeRPCClient command. The result of dp_MakeRPCClient is a handle that identifies the chosen RPC server. (Multiple connections are possible.) The doRPC command takes a Tcl command and sends it to a server to be executed. When the command completes, its result is returned as the result of the doRPC command. When the client is finished, dp_CloseRPC is used to close the connection cleanly. Tcl-DP is available from harbor.ecn.purdue.edu in the /pub/tcl/extensions directory.
24
data base
NSL TN-14
NSL TN-14
The state can be visible, or at least evident, to the user. For example, a checklist for ordering books can embed the state in the VALUE associated with a checkbox: <INPUT TYPE="checkbox" NAME="isbn" VALUE="034847X329"> Only a checkbox is displayed here. The title, author, and price of the book are displayed separately, next to the checkbox. (The checkbox is particularly convenient, because it always gives the user the option to deselect the item.) In this case, the state (the books ISBN number) isnt visible, but it is evident by the combination of the checkbox and the book information. It is important to remember that the embedded state will only be passed along if it is in a form that the user clicks the submit button for: If there are multiple forms in a document, the state must be embedded in each one. If the user clicks on a normal hyperlink, no form query will be processed, so the state wont be passed on.
26
NSL TN-14
27
NSL TN-14
Note that the CGI interface will probably have to be updated to pass the session identifier back and forth.
28
NSL TN-14
7. Additional Details
This chapter describes a number of small but important details that script authors should be aware of when designing and implementing their applications. You should be familiar with these issues, so that you will recognize them when you encounter them.
29
NSL TN-14
# Get the directory name of this script and cd to it. cd [file dirname $argv0] source setup.tcl The final need is to configure httpd to allow the files in the applications cgi-bin directory to be executed. The ScriptAlias command in the /usr/local/httpd/conf/srm.conf file does this: ScriptAlias virtual-path file-path For the Future Fantasy bookstore, this looks like (all on one line): ScriptAlias /palo-alto/FutureFantasy/cgi-bin/ /digital/hypertext/palo-alto/FutureFantasy/cgi-bin/
30
NSL TN-14
set env(PATH) "/usr/ucb:/bin:/usr/bin" puts {Content-type: text/html } flush stdout #----------------------------------------------------------# # Proc definitions. # # Get and return the value of an proc getenv {name} { global env if {[info exists env($name)]} return [format "%-16s %s" } else { return [format "%-16s %s" } } # # environment variable. { ${name}: $env($name)] ${name}: "<missing>"]
Attempt to execute <body>. If an error occurs, log the error message, send
31
NSL TN-14
# mail about it, and send an apologetic note to the user. proc handle_error {body} { global env problems logfile if {[catch {uplevel $body} msg]} { puts "<TITLE>Problem Processing Your Query</TITLE>" puts "<H1>Problem Processing Your Query</H1>" puts "While attempting to process your query, an unexpected problem was encountered: <UL> <LI><B>$msg</B> </UL> This error may have been caused by a problem in our software, but it is more likely that the query sent by the Web browser you are using was malformed. We have logged this error and will look into it. <P> Thank you for your patience." set mail " Error message: $msg [getenv SERVER_PROTOCOL] [getenv REQUEST_METHOD] [getenv CONTENT_TYPE] [getenv CONTENT_LENGTH] [getenv QUERY_STRING] Internet host: $env(REMOTE_HOST) ($env(REMOTE_ADDR)) In script: [info script] Active Command: [info level 0] " domail $problems "Unexpected error" "" "<<$mail" fappend $logfile [list error [string range [exec date] 4 end] $env(REMOTE_ADDR) $msg] exit } } # Check for the existance of the named query elements. # For any that are missing, send e-mail to the maintainers # and set the value to the empty string. proc check_query {args} { global Q problems env query logfile set missing "" foreach arg $args { if {! [info exists Q($arg)]} { lappend missing $arg set Q($arg) "" } } if {$missing != ""} { set msg " Missing names: $missing Query: $query [getenv SERVER_PROTOCOL] [getenv REQUEST_METHOD] [getenv CONTENT_TYPE] [getenv CONTENT_LENGTH] [getenv QUERY_STRING]
32
NSL TN-14
In script: [info script] Internet host: $env(REMOTE_HOST) ($env(REMOTE_ADDR))" domail $problems "Missing query components" "" "<<$msg" fappend $logfile [list error [string range [exec date] 4 end] $env(REMOTE_ADDR) [list missing $missing] $query] } } # Send the given file as a fax, to the appropriate number. # Normally: return 0, set <result> to the fax job number. # On error: return true, set <result> to the error message. proc dofax {file result} { upvar $result rv if {[catch { exec /usr/local/bin/sendfax -h phax -n -d 855-9963 $file } rv] != 0} { domail $problems "Future Fantasy fax problem" "" <<$rv return 1 } { set rv [lindex $rv 3] return 0 } } # Send mail to the correct people, taking input as specified # by <input>, which will usually be one of: # <<string or <<$variable # <filename or <$file # <@fileID or <@$fid # <to> says who to send the mail to. # <reply> is a reply-to address, which may be null. # <subject> is the subject line. proc domail {to subject reply input} { set fid [open "|mail $to" w] puts $fid "To: $to" if {$reply != ""} { puts $fid "Reply-To: $reply" } puts $fid "Subject: $subject" flush $fid exec cat $input >@$fid close $fid } # Append the given text to a file. proc fappend {file text} { set fid [open $file a] puts $fid $text close $fid } #----------------------------------------------------------# # Initial common processing of the query. #
33
NSL TN-14
handle_error {set query [cgi_get_query]} # # # if If the query is null, something is really wrong. Probably Mosaic didnt give anything to us, which happens in v2.2 when "Reload" is used. {$query == ""} { puts "<TITLE>Bug in Mosaic</TITLE>" puts "<H1>Bug in Mosaic</H1>" puts {Congratulations! You have tickled a small bug in Mosaic. You probably pushed the "reload" button on a page that you got to as the result of filling out a form. <P> Its nothing to worry about. To recover... <OL> <LI>Click on <B>Back</B>, to get to the page with the form. <LI>Click on the button you originally used to submit the query. </OL>} exit } cgi_parse_query -strip $query Q isbn
34
NSL TN-14
# Attempt to execute <body>. # If an error occurs, log the error and # send an apologetic note to the user. proc handle_error {body} { global env problems logfile if {[catch {uplevel $body} msg]} { puts "<TITLE>Problem Processing Your Query</TITLE>" puts "<H1>Problem Processing Your Query</H1>" puts "While attempting to process your query, an unexpected problem was encountered: <UL> <LI><B>$msg</B> </UL> This error may have been caused by a problem in our software, but it is more likely that the query sent by the Web browser you are using was malformed. <P> Thank you for your patience." fappend $logfile [list error [string range [exec date] 4 end] $env(REMOTE_ADDR) $msg] exit } }
35
NSL TN-14
36
NSL TN-14
37
NSL TN-14
The possible attributes are: TYPE="submit" specifies that this element is a submit button. NAME specifies the name for the buttons form data. If it is given, then a NAME=VALUE pair is added, corresponding to which submit button was clicked. This attribute is optional, and is not supported in Mosaic versions 2.4 and earlier. VALUE specifies the label to appear in the button (and be sent in the query). Optional: the default is "Submit". It is sometimes useful to have multiple possible actions within the same form. For example, when browsing a price list, you might want one button for "do more searching", and another for "place an order". In Mosaic 2.4 and earlier, it is possible to specify multiple submit buttons in a form, but scripts cant tell the difference between the buttons, because the buttons dont have names. The next version of Mosaic (after 2.4) should allow the NAME attribute, so this will eventually be a moot point.
38
NSL TN-14
The possible attributes are: TYPE="text" specifies that this element is a text entry field. TYPE="password" specifies that this element is a password field, which is just like text, except that the input is echoed with asterisks. NAME specifies the name for the form data. Required. VALUE specifies initial contents of the field. Optional. SIZE=width specifies the width of the field, in characters. This does not limit the amount of text that may be entered -- the field will scroll as necessary to accomodate more data. Optional: the default size is 20. SIZE=width,height specifies the width and height of the field, in characters and lines. This causes the field to have multiple lines. Optional. MAXLENGTH specifies the maximum number of characters that will be accepted as input. Optional: the default is unlimited.
The possible attributes are: TYPE="hidden" specifies that this element is a hidden data field.
39
NSL TN-14
NAME specifies the name for the form data. Required. VALUE specifies initial contents of the field. Optional.
I.6. Checkboxes
The TYPE="checkbox" element is used to get a single on/off value from the user. If the checkbox is checked, the NAME=VALUE pair will be present in the query. Otherwise, it will be absent. <INPUT TYPE="checkbox" NAME="olives" VALUE="yes"> Olives <BR> <INPUT TYPE="checkbox" NAME="mushrooms"> Mushrooms <BR> <INPUT TYPE="checkbox" NAME="cheese" CHECKED> Extra Cheese <P> <INPUT TYPE="checkbox" NAME="list" VALUE="16">16 <INPUT TYPE="checkbox" NAME="list" VALUE="8">8 <INPUT TYPE="checkbox" NAME="list" VALUE="4">4 <INPUT TYPE="checkbox" NAME="list" VALUE="2">2 <INPUT TYPE="checkbox" NAME="list" VALUE="1">1 <P> <INPUT TYPE="submit" VALUE="See Query"> <INPUT TYPE="reset">
The possible attributes are: TYPE="checkbox" specifies that this element is a checkbox. NAME specifies the name for the form data. Required. VALUE specifies value that will be returned in the query if the checkbox is selected. Optional: the default is "on". CHECKED specifies that the checkbox should be checked by default. Optional. If multiple checkboxes have the same NAME, one NAME=VALUE pair will be included in the query for each selected checkbox. The second set of checkboxes in the example demonstrates this.
40
NSL TN-14
The possible attributes are: TYPE="radio" specifies that this element is a radio button. NAME specifies the name for the form data. Radio buttons are grouped together by giving them the same NAME. Required. VALUE specifies the value that will be returned in the query if the checkbox is selected. Although the default is "on", radio buttons are not of much use unless different VALUEs are specified. CHECKED specifies that the radio button should be selected by default. Exactly one button in the group should be CHECKED.
41
NSL TN-14
Comments: <TEXTAREA NAME="comments" ROWS=4 COLS=40></TEXTAREA> <BR> Snide remarks: <TEXTAREA NAME="snide" ROWS=3 COLS=25> This stuff is boring! </TEXTAREA> <BR> <INPUT TYPE="submit" VALUE="See Query"> <INPUT TYPE="reset">
Note that the newlines inside the TEXTAREA tag are significant. That is why the "Snide remarks" text starts on the second line. The possible attributes are: NAME specifies the name for the form data. Required. ROWS specifies the height of the field, in lines. Optional. COLS specifies the width of the field, in characters. Optional.
42
NSL TN-14
Choose a lunch special: <SELECT NAME="pop-up"> <OPTION> Kung Pao Chicken <OPTION> Twice Cooked Pork <OPTION> Dry Braised Shrimp in Chili Sauce <OPTION> Szechwan Pepper Chicken <OPTION> Broccoli in Spicy Garlic Sauce <OPTION> Sweet and Sour Pork <OPTION> Shrimp with Assorted Vegetables <OPTION> Vegetable Delight </SELECT> <BR> Choose your toppings: <SELECT NAME="list" SIZE=6 MULTIPLE> <OPTION> Special Sauce <OPTION SELECTED> Lettuce <OPTION> Cheese <OPTION> Pickles <OPTION SELECTED> Onions <OPTION VALUE="ssb"> Sesame-Seed Bun </SELECT> <BR> <INPUT TYPE="submit" VALUE="See Query"> <INPUT TYPE="reset">
Notes: Use Shift-click to select a range of items. Use Control-click to select multiple discontiguous items. If none of the list items are selected, that NAME will not be present in the query. The NAME list is given as a list-name in the cgi_parse_query command, so the "toppings" are accumulated into a Tcl list. Note that "Sesame-Seed Bun" is represented as "ssb" in the query, because the VALUE attribute is given for it. The possible attributes for the SELECT tag are: NAME specifies the name for the form data. Required. SIZE specifies the number of rows in the list. If SIZE is 1 or omitted, the SELECT will be represented with a pop-up menu, otherwise with a scrolling list with the given number of rows.
43
NSL TN-14
MULTIPLE specifies that the SELECT should allow multiple selections. MULTIPLE forces the SELECT to be represented with a scrolling list, with a default SIZE of 5. Optional. The possible attributes for the OPTION tag are: SELECTED specifies that this option is selected by default. Multiple options can be selected, if the MULTIPLE attribute is present in the SELECT tag. VALUE specifies the value to be returned in the query when this option is selected. By default, the value is the same as the text in the option. VALUE is new as of X Mosaic version 2.2.
I.10. Images
NCSA Mosaic version 2.2 allows bitmap images to be used as input elements in forms. However, it is not a part of the official HTML specification, so its use may not be supported in all HTML viewers. Click me: <INPUT TYPE="image" NAME="image" ALIGN=TOP SRC="myself.gif">
When the user clicks on the displayed image, the (x,y) coordinates are put into the query as name.x and name.y and the query is immediately sent. For example: test.x=35 test.y=82 Coordinates are relative to the upper-left corner of the image, measured in pixels. Unlike all of the other FORM input elements, the submit button is not required, because clicking on the image submits the query. The possible attributes are: TYPE="image" specifies that this element is an image. NAME specifies the name for the form data. Required.
44
NSL TN-14
SRC specifies the URL of the image to display. This is subject to the same restrictions as any other inline image. i.e., the format may only be GIF (.gif) or X-bitmap (.xbm). Required. ALIGN can be either TOP or BOTTOM, specifiying how to align the image relative to the surrounding text. Optional: the default is BOTTOM.
45