cgi.tcl - A Reference Manual (Draft)
by Don Libes

This document contains technical notes on using cgi.tcl.  This
document is a draft and has not been officially reviewed.

This document assumes that you have read the Tcl '96 paper "CGI
Scripting in Tcl".  That document will give you the feel for what this
code is all about.  In contrast, this document provides the details.

This document assumes you know HTML.  I'm not going to explain what
particular tags do or how to use them effectively, except as necessary
to understand the document.

Some of the commands may not work with all browsers.  For example, the
cgi_center command is generally understood only by some Netscape
browsers because it produces <center></center> tags which are not
commonly supported.  You'll have to use your judgement.  Remember:
Just because a command exists to produce the HTML doesn't mean your
browser will do anything meaningful with it.  In that sense, using
this code is no different than handcoding HTML.

**************************************************
A NOTE ABOUT PROCEDURE NAMES
**************************************************

All procedures are named cgi_XXX.  You can also call them without the
cgi_ prefix.  Using the cgi_XXX form is no big deal for rarely used
procedures, but the aliases are particularly convenient for things
like hr and br.  Aliases are suppressed if procedures exist by those
names already.  (Thus, cgi_eval cannot be invoked as "eval"!)
Similarly, you can overwrite the aliases with impunity.  Internally,
references are only made to the cgi_ names.

I'm still thinking about this.  If you have strong feelings about it,
let me know.

**************************************************
SECURITY
**************************************************

I frequently see statements saying that Tcl (and other interpretive
languages, for that matter) are insecure and should not be used for
writing CGI.

I disagree.  It is possible to use Tcl securely and it really isn't
very hard.  The key, of course, is to not blindly evaluate user input.
There really isn't much reason to.  For instance, this library itself
is pretty big and does lots of things, but nothing in it evaluates
user input.  (It does do a lot of evaluation of *programmer* input,
but that's quite acceptable.)

The two classes of commands you should pay close attention to are
commands that do eval operations and commands that invoke external
programs.  

**************************************************
GENERAL NOTES ABOUT PARAMETERS
**************************************************

** There are several basic styles of parameter passing.

-- Container commands (e.g., <body></body>, <div></div>, etc.)

The last argument is typically a block of code.  Other arguments
become attributes.  For example:

  cgi_body bgcolor=red background=white {
	h4 "hello"
  }

produces:

  <body bgcolor="red" background="white">
        <h4>hello</h4>
  </body>

-- Commands with required arguments

Some commands have required arguments.  Required arguments which are
relatively long, are passed *after* all others.  For example:

  cgi_h4 align=left "Foo's Bar & Grill"

Another example:

  cgi_body bgcolor=red background=white {
    cgi_h4 "Foo's Bar & Grill"
  }

Commands with relatively short arguments have the short arguments
passed *before* all others.  This avoids many redundant keywords.  In
the following example, the "img=" is omitted because it is already
implied by the command.  The "alt=" is not optional (although the
entire argument is).

  cgi_img foo.gif "alt=Foo's Bar & Grill"

Note the quotes around the alt argument.  This is only necessary if
the argument has whitespace in it - a consequence of Tcl's normal
scanning rules.  The resulting HTML automatically includes quotes
around the value attribute.  (See Case-sensitivity.)

** Case-sensitivity and Quotes and Whitespace

Attribute names are case sensitive.  Use lowercase names for "normal"
handling.  For example, values for attributes such as "url" and
"value" are quoted and encoded.  Use uppercase names to suppress the
usual processing.  (For example, you might want to test how a browser
responds to incorrect HTML.)

Consider:

  cgi_body bgcolor=#123456 {
    cgi_img foo.gif "alt=Foo's Bar & Grill"
  }

This is translated to

  <body bgcolor="#123456">
    <img src="foo.gif" alt="Foo's Bar &amp Grill">
  </body>

Notice how the ampersand in the alt value has been encoded.  Also
notice how quotes have been added to the values of bgcolor, url, and
alt.  Thus you no longer have to add quotes all over the place (or
remember when you need to).

Embedded whitespace is protected by quoting in the usual Tcl fashion
rather than typical HTML fashion.

So instead of:
   img foo.gif alt="foo bar"
do this:
   img foo.gif "alt=foo bar"
which will produce HTML that is properly quoted:
   <img src="foo.gif" alt="foo bar">

-- Name-value commands

Many commands produce tags that use "name" and "value" attributes.
Because these attributes are almost always used in such commands, the
first argument is always of the form name=value so the literal "name"
and "value" can be omitted.  For example:

  cgi_text color=Red size=5

produces:

  <input name="color" value="Red" size=5>

Reasonable defaults exist.  For example, if you don't need the value
of a submit button (but the user still needs to see it appear as the
label), omit the name:

  cgi_submit_button =Execute

If no "=" is present, the string is assumed to be the "name"
attribute.  For example:

  cgi_checkbox Vegies

produces a checkbox associated with the variable named "Vegies".
(With no specified value, it will be set to "on" if checked.)

Most of the commands have reasonable defaults.  For example, to
quickly script a submit button, the following suffices:

  cgi_submit_button

Certain constructions make no sense and are therefore disallowed.  For
example, a submit button with a name but no value makes no sense, so
cgi_submit_button doesn't allow it.  (In other words, if you provide
an argument, it has to have "=" in it.)

**************************************************
JAVASCRIPT ARGUMENTS
**************************************************

JavaScript event attributes such as onClick are handled just like any
other attributes in terms of quoting and case sensitivity.  Because
there are so many attributes on so many tags, they are not documented
explicitly in this manual.  However, they are all supported.  Here is
an example:

  cgi_text age=18 onChange=MinimumAge(this.form.age)

**************************************************
PROCEDURES TO ASSIST IN DEBUGGING
**************************************************

** User-id differences

You can interactively run and debug CGI scripts by simply running them
from the shell, or a Tcl or C debugger.  (For convenience, I use
Expect instead of tclsh just so that I get the debugger.)  In fact,
I've never had to resort to the C debugger.  However, simply watching
the raw output from a shell is very handy.  This catches the really
basic errors such as incorrect protections, incorrect #! line, etc.
Once your script is actually executing, you can rely on cgi_eval (see
below).

cgi_uid_check user

Typically, a CGI script is intended to run from a particular uid, such
as "nobody".  If you run such scripts interactively, you can end up
with conflicts.  For example, if the script creates files, files can
accidentally end up being owned by you.

cgi_uid_check is a convenient mechanism to warn against this problem.
Simply call cgi_uid_check in your script.  The argument is the uid
under which the script should be running.  If the given uid does
not match the actual uid, cgi_uid_check will generate an error.

** Trapping error messages

cgi_eval

cgi_eval is the primary error catching/reporting mechanism.  Execute
commands from cgi_eval so that errors can be caught and reported in a
nice way.  By default, errors are emailed back to the administrator.
"cgi_debug -on" makes errors be immediately viewable in the browser.

cgi_error_occurred

cgi_error_occurred returns 1 if an error occurred and was caught by
cgi_eval.  This separate function simplifies exit handling - for
example, rather than always checking the return value of cgi_eval, an
app can just test this from a redefined exit.

cgi_admin_mail_addr addr

cgi_admin_mail_addr sets the administrator's email address.
Diagnostics are sent via email if a problem is encountered with the
script and debugging is not enabled.

cgi_name name

cgi_name defines a name for the service.  If called with no arguments,
the name is returned.  The name is currently used in the following
places:

  If email is sent, it comes from [cgi_name].
  If errors are emailed, the subject is "[cgi_name]: CGI problem"

** Generating debugging output and other commands

cgi_debug args

cgi_debug provides rudimentary support for generating debugging
messages.  Here are some example calls:

cgi_debug cmd
	If debugging is on, the command is evaluated.  For example:

	  cgi_debug {
	    h2 "completed initialization"
	  }
	or
	  cgi_debug {h2 "completed initialization"}

	Note this is more than simply calling h2.  Context is rewound
	or forwarded to get to a place where this is safe.  (And
	conversely, this call can suppress things such as header
	elements that haven't been processed yet.)  The flag
	"-noprint" suppresses this manipulation - this is useful for
	early code that causes no printing.

	The -- flag causes the next argument to treated as a command
	even if it looks like another flag.
cgi_debug -on
	Enables debugging messages.  This includes debugging messages
	generated by explicit calls to cgi_debug as well as implicit
	diagnostics, for example, that report on form input.
cgi_debug -temp text
	Enable debugging for this one line.
cgi_debug -off
	Disable debugging.

cgi_debug always returns the old setting ("-on" or "-off").  The
initial value is -off.


** Printing arrays

cgi_parray arrayname

cgi_parray prints out the elements of a Tcl array.  cgi_parray is just
like Tcl's parray except that its output is appropriately formatted
for a browser.

**************************************************
BASIC STRUCTURE OF A CGI SCRIPT
**************************************************

Typically, the basic structure of most CGI scripts is:

  package require cgi

  cgi_eval {
    cgi_http_head {cmds}
    cgi_html {
      cgi_head {cmds}
      cgi_body {cmds}
    }
  }

Much of this can be omitted, however.  In fact, a typical script looks
more like this:

  package require cgi

  cgi_eval {
    cgi_title "title"
    cgi_body {
      cmds
    }
  }

(If you're not using the Tcl package support, replace the 'package
require' command with a 'source' command of the specific file
containing the cgi.tcl source.)

(The "...." in the examples above should be replaced by the true path
to the cgi.tcl file.)

I'll now go through each of these in more detail as well as some other
possibilities for the overall structure.

**************************************************
HTTP HEADERS
**************************************************

cgi_http_head cmds

CGI scripts must produce various headers to explain how the remainder
of the output is to be interpreted.  No other output may preceed this!

With no argument, an HTML content type is produced if the script is
running in the CGI environment.  This means that most people need not
bother calling cgi_http_head.  However, if you want to see the HTTP
headers and you are not running in the CGI environment, you should
call cgi_http_head explicitly.  (Alternatively, you can make it appear
that you are in the CGI environment by defining the environment
variable REQUEST_METHOD.)

The remaining commands in this section may be used in cgi_http_head.
Most should be intuitively obvious and thus need no explanation.

cgi_content_type type
	Generates a "Content-type:" header.

With no argument, cgi_content_type generates a declaration for HTML.
If specified, the 'type' argument should be the full MIME-style
type/subtype declaration.  Any MIME-style parameters should be
included in the type argument.

cgi_redirect location
	Generates a redirect header (Status:/Location:/URI:)
cgi_target
	Generates a "Window-target:" header.
cgi_refresh seconds url
	Generates a "Refresh:" header.  The url argument is optional.
cgi_pragma pragma
	Generates a "Pragma:" header.
cgi_status number string
	Generates a "Status:" header.

** Cookies

cgi_cookie_set name=val args
	Define a cookie with given name, value, and other arguments.
	Cookie values are automatically encoded to protect odd characters.
	A couple expirations are predefined (with intuitive meaning):
	  expires=never
	  expires=now
	  expires=...actual date...

	Here are some examples:
	  cgi_cookie_set user=don domain=nist.gov expires=never
	  cgi_cookie_set user=don expires=now secure

cgi_export_cookie name args
	Export the named Tcl variable as a cookie.  Other arguments are
	processed as with cgi_cookie_set.

Cookies may be read only after calling cgi_input.  The following
routines read cookie names or specific cookies.

cgi_cookie_list
	Returns the list of all cookies supplied by the server.

cgi_cookie_get name
	Returns the value of the named cookie.  If multiple values exists
	the most specific path mapping is used.

	If the "-all" flag is used (before the cookie name), a list is
	returned containing all cookie values for the given name.  The
	list is ordered most-specific (path mapping) to least.  I.e.,
	the first value on the list is the same one returned by
	calling cgi_cookie get without a flag.

cgi_import_cookie name
	Define a Tcl variable with the value of the cookie of the same
	name.  For example, the following command retrieves the cookie
	named "Password" and stores it in the Tcl variable "Password".

	  cgi_import_cookie Password

cgi_import_file -server name
cgi_import_file -client name
cgi_import_file -type name

cgi_import_file returns information about an uploaded file.  "name" is
the string from the original form.  The Content-type is returned via
-type.  (This may be empty or even undefined in which case
cgi_import_file should be caught.)

Uploaded files are saved on the CGI server.  To avoid collisions with
other file upload instances, files are not stored in their original
names.  The name of the file as it is stored on the CGI server is
retrieved using the "-server" flag.  The original name of the file as
it was stored on the user's host is retrieved using the "-client"
flag.

Uploaded files are the responsibility of the CGI programmer.  In
particular, if you do not delete them, they will remain until /tmp is
cleaned up in some other way.

If the user does not enter a filename, an empty file will be delivered
with a null remote filename.

For example, the following code echos the contents of a file that was
uploaded using the variable "file":

  cgi_input
  cgi_body {
    set server [cgi_import_filename -server $v]
    set client [cgi_import_filename -client $v]
    if [string length $client] {
      h4 "Uploaded: $client, contents:"
      cgi_preformatted {puts [exec cat $server]}
    }
    exec /bin/rm -f $server
  }

The present implementation supports binary upload if you are using Tcl
8.1 (or later) or if you are using the Expect extension.  If you are
using a version of Tcl earlier than 8.1 with Expect but want to
suppress binary loading, create the global variable
_cgi(no_binary_upload).  (The reason you might want to suppress binary
loading is that it is noticably slower.)


**************************************************
GENERATING HTML
**************************************************

cgi_html

<html></html> tags can be generated using cgi_html.  An argument to
cgi_html is evaluated to produce the actual HTML code.

In practice, it is not necessary to use cgi_html.  CGI.tcl will
automatically generate the tags when appropriate.  (Oddly, modern HTML
specs don't require it and most if not all browsers never cared
anyway.)

cgi_doctype

cgi_doctype is a user-defined procedure that produces a SGML DOCTYPE
declaration.  If it exists, cgi_doctype is automatically invoked at
the beginning of cgi_html.  (This library does not automatically create
DOCTYPE declarations since the library is not restricted to generating
SGML for any single DTD.  Realistically, DOCTYPEs are pointless for
HTML generation since web browsers don't require DOCTYPE declarations.
However, if you are creating pages for some other purpose that
requires such a declaration, use cgi_doctype.)

cgi_head

<head></head> tags can be generated using cgi_head.  An argument to
cgi_head is evaluated to produce the actual headers.

In practice, it is not necessary to use cgi_head.  CGI.tcl will
automatically generate the tags when appropriate.  (Oddly, modern HTML
specs don't require it and most if not all browsers never cared
anyway.  So for example:

  cgi_head {
    cgi_title "my page"
  }

is equivalent to:

  cgi_title "my page"

Note that cgi_title will be called automatically if you omit
cgi_title, cgi_head, or call cgi_head with no arguments.

cgi_title title

cgi_title defines the title of a page.  It is called from within a
<head></head> pair.  If not called from within cgi_head, it implicitly
forces it to occur.

cgi_title always returns the title.  With no argument, cgi_title
returns the old title without changing it.

cgi_http_equiv

cgi_http_equiv is equivalent to cgi_http_head but from within
cgi_head.  This procedure is defined for completeness - there is no
reason to use it.  In fact, it doesn't allow all cgi_http_head
declarations, so it should be avoided.

cgi_meta

cgi_meta generates a <meta> tag.  You can do whatever you want with
these.  (Read some an HTML document for more info.)  For example:

  meta name=author {content="Don Libes"}

cgi_script cmd

cgi_script evaluates its arguments inside of <script></script> tags.
This is appropriate for putting in client-side scripting.  Optional
arguments are passed as attributes to the <script> tag.

Note that the cmd argument is a Tcl command, not a command in the
other scripting language.  So if all you want to do is print out some
script, use cgi_puts:

  cgi_script {
    cgi_puts {
      some scripting stuff
        in whatever weird funky
        language you want
    }
}

cgi_javascript cmd

cgi_javascript is a version of cgi_script specialized for javascript.
At present, all it does is add the comment hacks so that the
javascript can't be seen by old browsers.

cgi_noscript cmd

cgi_noscript evaluates its argument to generate code for browsers that
do not understand cgi_script or its variants.

cgi_body

<body></body> tags are generated using cgi_body.  An argument to
cgi_body is evaluated to produce the actual body.

Executing "return" from within cgi_body causes cgi_body to return.
This is useful if more code follows the cgi_body within the cgi_eval.
Compare to cgi_exit (see elsewhere).

cgi_body_args

Arguments to cgi_body_args are made available to cgi_body as if they
had been specified in the call to cgi_body.  This provides a
convenient way for using the same colors, backgrounds, etc, in a set
of pages.

cgi_exit

cgi_exit provides a fast way of cleanly exiting a CGI script without
having to manually unwind procedures.  In particular, cgi_exit forces
closure of all open tags.  It then calls exit.  This is useful if you
want to exit from a CGI script at any point and still have the HTML be
correct.

** Frames

cgi_frameset cmd

Instead of cgi_body, you can call cgi_frameset to create framed
documents.  This produces <frameset></frameset> tags with the content
filled by evaluation of cmd.  Optional arguments are passed on as
attributes.

cgi_frame name=url

cgi_frame defines a frame with the given name and url.  The argument
handling is the same as for other name-value commands (even though the
value here is a url).  The url is automatically double-quoted.  Other
optional arguments are passed on as attributes.

cgi_noframes cmd

cgi_noframes produces <noframes></noframes> tags with the content
filled evaluation of cmd.  Optional arguments are passed on as
attributes.

**************************************************
CONTAINER SUPPORT
**************************************************

cgi_division

cgi_division evaluates its last argument, grouping it together.  This
is useful for acting on a group of paragraphs, such as for alignment
purposes.

cgi_center

cgi_center is similar to "cgi_division align=center".

**************************************************
SINGLE PARAGRAPH SUPPORT
**************************************************

Everything in this section generates a single paragraph or line break.
Most of these take a string as the last argument which is
appropriately formatted.  Any other arguments are used as tag
attributes.

cgi_p
cgi_address
cgi_blockquote
cgi_h1 through h7

Most of these procedures should be intuitive.  They all take a string
and display it in the appropriate way.  For example, a level 2
heading:

  h2 "Paragraph Support"

Here's a paragraph with some formatting (see next section for more
info):

  p "I [bold love] Tcl but hate [blink "blinking text"]"

Note that some of these generate tags that are not supported by all
browsers.  See the format-tour.cgi script to see these in use.

cgi_br

cgi_br causes a paragraph break to be printed.  Additional arguments
are passed on as attributes.

To embed a paragraph break (rather than printing it), use cgi_nl.  In
the following example, it is much more convenient to call cgi_br than
cgi_nl:

  radio_button "version=1"
  br
  radio_button "version=2"

See cgi_nl for more info.

**************************************************
TEXT SUPPORT
**************************************************

The following procedures take a string and return an appropriately
formatted version.  The string is always the last argument.  Any other
arguments are used as tag attributes.

cgi_bold
cgi_italic
cgi_underline
cgi_strikeout
cgi_subscript
cgi_superscript
cgi_typewriter
cgi_blink
cgi_emphasis
cgi_strong
cgi_cite
cgi_sample
cgi_keyboard
cgi_variable
cgi_definition
cgi_big
cgi_small
cgi_font

  p "I [bold love] Tcl but hate [blink "blinking text"]"

Note that some of these generate tags that are not supported by all
browsers.  See the format-tour.cgi script to see these in use.

cgi_basefont

cgi_basefont defines the base font.

**************************************************
SPECIAL CHARACTERS OR CHARACTER SEQUENCES
**************************************************

The following procedures produce characters such that when interpreted
by a browser returns the indicated character.

                      	Returns
cgi_lt			<
cgi_gt			>
cgi_amp			&
cgi_quote		"
cgi_enspace		en space
cgi_emspace		em space
cgi_nbspace		nonbreaking space
cgi_tm			registered trademark
cgi_copyright		copyright
cgi_isochar n		ISO character #n

cgi_nl

cgi_nl returns a paragraph break string suitable for embedding in a
string just as you would embed a newline in a Tcl string via \n.

To print a paragraph break rather than returning it, use cgi_br.  In
the following example, it is much more convenient to call cgi_nl than
than cgi_br:

  h2 "This appears[nl]on two lines."

See cgi_br for more info.

cgi_breakable

cgi_breakable indicates a place in a word at which the browser can
break a string across two lines.

cgi_unbreakable cmd

cgi_unbreakable evaluates a cmd in such a way that the output will not
be broken across lines by the browser just because the screen width is
exceeded.  Instead a horizontal scrollbar will appear so that the
browser can be manually scrolled to see the long line.
n
cgi_unbreakable_string string

cgi_unbreakable_string returns its arguments so that it will not be
broken across lines by the browser just because the screen width is
exceeded.  Instead a horizontal scrollbar will appear so that the
browser can be manually scrolled to see the long line.

Notes:

- It is my assumption that cgi_unbreakable will be much more commonly
used than the _string version, hence the choice of names.  Feel free
to let me know what I'm wrong.

- I have seen browsers handle unbreakables incorrectly, particularly
in interaction with other features.  If you can't get your
unbreakables to behave correctly, consider alternative layouts or
alternative HTML.  For example, unbreakable table data should be done
using "table_data nowrap".  I have no idea why but it works whereas
unbreakable causes the table rows to overlap.  Clearly, this is a
browser bug.

**************************************************
FORMS
**************************************************

cgi_form action args cmd

cgi_form defines a form.  The form is populated by executing the
command (last argument of cgi_form).  action defines the url to
process the form.  Any other arguments are passed as attributes.
A typical call looks like this:

  cgi_form response {
    ....
  }

Here "response" names the URL to process the form.  If the URL does
not begin with a protocol name (such as "http:"), a common root is
prepended and ".cgi" is appended.  This can be changed by redefining
the procedure cgi_cgi.

cgi_root

cgi_root defines the common root used by cgi_form (see above).
For example:

  cgi_root "http://www.nist.gov/cgi-bin/cgi.tcl-examples"

With one argument, cgi_root returns the new root.  With no arguments,
cgi_root returns the old root.

cgi_suffix

cgi_suffix defines the common suffix used by cgi_cgi and anything that
uses it such as cgi_form.  The default suffix is ".cgi".

cgi_cgi
cgi_cgi_set

cgi_cgi controls exactly how cgi_form creates URLs from its action
argument.  By default, cgi_cgi takes an argument, prepends [cgi_root]
and appends [cgi_suffix].  The suffix can be overridden by using the
-suffix flag and an argument to be used instead of [cgi_suffix].

Any additional arguments are joined together in the style required for
a GET style request.  These arguments should be preformatted using
cgi_cgi_set to guarantee proper encoding.  For example:

  cgi_cgi myscript \
     [cgi_cgi_set owner "Don"] \
     [cgi_cgi_set color "black & white"]

generates: ....?owner=Don&color=black+%26+white


cgi_isindex

cgi_isindex generates an <isindex> tag.  Optional arguments are passed
on as attributes.  In the processing CGI script, the value of the
isindex query is found in the "anonymous" variable.

cgi_relationship rel url

cgi_relationship expresses a relationship between this document and
another.  For example, the following says that the url named by
homepage is the home document of the current document.

  cgi_relationship home $homepage

Optional arguments are passed on as additional attributes.  Here's an
example that references an external style sheet that is a CSS type
(cascading style sheet).

  cgi_relationship stylesheet basic.css type=text/css


**************************************************
INPUT
**************************************************

cgi_input

CGI input means "cookies, files, and get/post data".  cgi_input reads
in all input, decodes it, and makes it available to a variety of other
routines.

For debugging, cgi_input can be given arguments to fake input.  This
allows you to run your cgi_script interactively or under a debugger
(either Tcl or C debugger).  Provide GET/POST data as the first
argument.  Provide cookie data as the second argument.  The arguments
should be encoded (see cgi_cgi_set).  For example:

  cgi_input "name=libes&old=foo&new1=bar&new2=hello"

This is convenient because when you run into a misbehaving CGI script,
the first thing it does is tell you the input in exactly this format.
Now simply cut and paste it into your program and you can then
interactively debug it without using the real form or the CGI server.

If cgi_input is invoked from the CGI environment, the fake inputs are
ignored.  (If you want to force fake inputs in the CGI environment,
unset env(REQUEST_METHOD).

Forms encoded as multipart/form-data are usually used to handle file
input.  Since file data usually implies a large amount of data, the
data is saved to /tmp/CGIdbg.[pid] if debugging is enabled.  This file
can be fed back to cgi_input by providing the filename as the first
argument of cgi_input.  In addition, env(CONTENT_TYPE) must be set to
the appropriate content type.  This can found in env(CONTENT_TYPE).
Removal of the debugging file is the responsibility of the script or
the script programmer.  (Typically, I examine the file after my CGI
script is over and then delete them by hand.)

Execs before cgi_input reads POST data should have standard input
redirected ("< /dev/null" for instance) so that the exec'd process
doesn't inherit the CGI script's standard input.

** Form elements that generate lists

Variable names should only end with "List" if they correspond to form
elements which generate multiple values (some but not all uses of
select, checkbox, etc).  List variables will be given Tcl-style list
values.

cgi_input enforces this restriction by issuing diagnostics when it can
detect violations.

This is done in order to distinguish whether a value such as "foo bar"
is a single element "foo bar" or two elements "foo" and "bar".

Here are examples:

  # pull-down menu
  cgi_select Foo {
    cgi_option "a"
    cgi_option "a b"
  }

  # scrolled list, allow multiple selections
  cgi_select FooList multiple {
    cgi_option "a"
    cgi_option "a b"
  }

** Getting at the input

Input is made available in two ways: variables and cookies.

-- Variables

cgi_import_list

cgi_import_list returns a list of variable names supplied as input to
the script.

cgi_cookie_list

cgi_cookie_list returns a list of cookie names supplied to the script.

cgi_import name

cgi_import retrieves the value of the named variable and places it in
a Tcl variable of the same name.  The value is also returned as the
return value.

cgi_import_as name tclvar

cgi_import_as is similar to cgi_import but the value is assigned to
the Tcl variable named by the second argument.

cgi_import_cookie name

cgi_import is similar to cgi_import, however if the cgi variable does
not exist, the value is fetched from the cookie by that name.  (This
allows the user to override a cookie if the form allows it.)

cgi_import_cookie_as name tclvar

cgi_import_cookie_as is similar to cgi_import_cookie but the value is
assigned to the Tcl variable named by the second argument.

cgi_cookie_get name

cgi_cookie_get returns the value of the named cookie.

**************************************************
EXPORT
**************************************************

Form elements automatically export their values.  See FORM ELEMENTS
for more information.

cgi_export name=value

cgi_export makes the named variable available with the given value.
The "=value" is optional.  If not present, the value of the Tcl
variable by the same name is used.  

cgi_export is implemented with variables of type=hidden.

cgi_export is implemented as an all-or-nothing operation.  In
particular, no HTML is emitted if the variable does not exist.  That
means it is not necessary to test for existence in situations where
you would like to export a variable IF it exists.  Rather, it is
sufficient to embed cgi_export within a catch.  For example, the
following generates nothing if xyz doesn't exist and it generates the
appropriate HTML if xyz does exist.

  catch {cgi_export xyz}

** Cookies

cgi_export_cookie name

cgi_export_cookie is similar to cgi_export except that the value is
made available as a cookie.  Additional arguments are handled as with
cgi_cookie_set (see below).

cgi_cookie_set name=val

cgi_cookie_set sets the named cookie.  All optional arguments are
handled specially.  All arguments are encoded appropriately.  The
expires keyword is handled specially to simplify common cases.  In
particular, the values "now" and "never" produce appropriate GMT
values.

Here are some example of cgi_cookie_set:

  cgi_cookie_set user=don domain=nist.gov expires=never
  cgi_cookie_set user=don domain=nist.gov expires=now
  cgi_cookie_set user=don domain=nist.gov expires=...actual date...

Note that cookie setting must be done during http head generation.

**************************************************
URL/IMG DICTIONARY SUPPORT
**************************************************

cgi_link tag
cgi_link tag display url

cgi_link provides a convenient mechanism for maintaining and
referencing from a set of URLs.

cgi_link returns the string <A>...</A> corresponding to the given tag.
A tag is defined by calling cgi_link with the tag, the clickable text
that the use should see, and the url.

For example, suppose you want to produce the following (where _xyz_
indicates xyz is a hyperlink):

  I am married to _Don Libes_ who works in the _Manufacturing
  Collaboration Technologies Group_ at _NIST_.

Using cgi_link with appropriate link definitions, the scripting to
produce this is:

  p "I am married to [link Libes] who works in the [link MCTG]
  at [link NIST]."

This expands to:

  I am married to <A HREF="http://elib.cme.nist.gov/msid/staff
  /libes/ libes.don.html">Don Libes</A> who works in the <A
  HREF="http:// elib.cme.nist.gov/msid/groups/mctg.htm">
  Manufacturing Collaboration Technologies Group</A> at <A
  HREF="http:// www.nist.gov">NIST</A>.

The links themselves are defined thusly:

  link Libes "Don Libes"    http://www.cme.nist.gov/msid/staff/libes
  link MCTG  "$MCT Group"   http://www.cme.nist.gov/msid/mctg
  link NIST  "NIST"         http://www.nist.gov

Now if my home page ever changes, rather than updating every
occurrence, I just have to edit the one definition.

Tcl variables can further simplify updates.  For instance, URLs for
Libes and MCTG are in a common directory.  It makes sense to store
that in a single variable.  Rewritten this appears:

set MSID http://www.cme.nist.gov/msid

  link Libes "Don Libes"    $MSID/staff/libes
  link MCTG  "$MCT Group"   $MSID/mctg
  link NIST  "NIST"         http://www.nist.gov

Then if the MSID directory ever moves, only one line need be updated.
This may seem like no big deal here, but if you have many links and
many uses of them, this pays off handsomely.

Optional attributes can be provided as additional arguments (see IMG
example below).

An existing link can be given a different "display" temporarily by
calling cgi_link with the different display and omitting the url.

cgi_imglink 

imglink works similar to cgi_link (see that documentation for more
info) except that no display argument is used and the second argument
is assumed to be the image source.  Example:

  imglink taj tajmahal.gif

Other attributes can be provided as additional arguments.

  imglink taj tajmahal.gif alt="The Taj Mahal"

cgi_url display href args

By using cgi_url, URLs can be generated immediately (without using
cgi_link first).  This is convenient when you need a URL that will
only appear once - so that there is no point in storing it in a
dictionary.  For example:

  cgi_li "[cgi_url "Plume" http://pastime.anu.edu.au/Plume]
      is a Tcl-based WWW browser written by Steve Ball,
      Australian National University.  Among its interesting
      features is the ability to execute Tcl applets and the
      ability to dynamically extend the browser at runtime."

cgi_img href args

cgi_img returns a formatted <img> tag.  It is useful for one-time tags.
Tags that are used multiple times should use cgi_imglink.  Example:

  cgi_img foo.gif "alt=Foo's Bar & Grill"

cgi_anchor_name name

cgi_anchor_name returns an anchor that can be used in an HTML body
that it can be linked to using the #name syntax.  For example, to make
a heading that you want to be able to link to:

  h2 "[cgi_anchor_name future]Future Improvements"

Then to reference the "future" tag:

  p "Look for [cgi_url "improvements" future] in the future."

cgi_base args

cgi_base defines a base or window target for urls.

**************************************************
QUOTING
**************************************************

cgi_unquote_input string

cgi_unquote_input undoes "url-encoding" and returns the result.  This
is normally applied automatically to input sources including URLs and
cookies.  So you shouldn't have to call this manually.

cgi_quote_html string

cgi_quote_html returns the string but with any html-special characters
escaped.  For example, "<" is replaced by "\&lt".  This is useful for
displaying a literal "<" in the browser.

cgi_dquote_html string

cgi_dquote_html does the same thing as cgi_quote_html but also adds on
double quotes.  cgi_quote_html is called automatically for implicit
value attributes.

cgi_quote_url string

cgi_quote_url quotes strings appropriately to appear in a url, cookie,
etc.  This is useful if you want to publish a url by hand (and must do
the conversion manually that the client normally does for you).

If you are generating cgi-style URLs for forms, use cgi_cgi_set.

cgi_preformatted cmd

cgi_preformatted evaluates its last argument to produce fixed-width
preformatted output.  Optional arguments are passed as attributes to
the tags.

cgi_preformatted allows a subset of tags to be interpreted by the
browser.  For example, the <a> tag is interpreted but font change tags
are not.  To prevent all interpretation, use cgi_quote_html.  For
example, the following prints a file that might contain HTML but
without any risk to throwing off formatting.

  cgi_preformatted {
    puts [cgi_quote_html [read $fid]]
  }

**************************************************
LIST SUPPORT
**************************************************

** List elements

cgi_li string

cgi_li prints its string as a list element.  Optional arguments are
passed through as attributes.  cgi_li does not have to appear in a
list container, but it can.

cgi_term text
cgi_term_definition text

cgi_term and cgi_term_definition are usually paired up (although they
need not be) to creates terms and defintions.  They do not have to
appear in a list container, but usually appear in a cgi_definition_list.

** List containers

cgi_number_list cmd
cgi_bullet_list cmd

cgi_number_list and cgi_bullet_list take their cmd argument and
evaluate it in a list container context.  (I don't know about you but
I could never remember <ol>, <ul>, and all the other ones.  This names
seem much easier to remember.)

cgi_li is a typical command to call inside of a list container, but
you can use regular paragraphs (or anything else) as well.

cgi_definition_list

cgi_definition_list is the usual list container for cgi_term and
cgi_term_definition.  It may contain other things as well.

cgi_menu_list
cgi_directory_list

cgi_menu_list and cgi_directory are more list containers with the
obvious semantics.  Previous remarks about other list containers
apply.

**************************************************
TABLE
**************************************************

cgi_table cmd

cgi_table produces <table></table> tags with the content filled by
evaluation of cmd.  Optional arguments are passed on as attributes.

cgi_caption cmd

cgi_caption produces <caption></caption> tags with the content filled
by evaluation of cmd.  Optional arguments are passed on as attributes.

cgi_table_row cmd
cgi_table_head cmd
cgi_table_data cmd

These functions all produce the appropriate tags with the content
filled by evaluation of cmd.  Optional arguments are passed on as
attributes.

cgi_tr table_data
cgi_td table_data
cgi_th table_data

cgi_tr, cgi_td, and cgi_th are shortcuts for relatively simple rows.

cgi_td outputs a table element.  Unlike cgi_table_data, the argument
is not evalled.  This allows more terse specification of simple rows.
The following example produces a table with three elements, the last
of which is prevented from wrapping:

  table_row {td Don;td Steve;td nowrap "Really Long Name"}

As the example suggests, optional arguments are passed on as
data-specific attributes.

cgi_th is identical to cgi_td except that it produces table heading
elements.

cgi_tr outputs a row of elements without having to call cgi_td or
cgi_table_data.  As with td, eval is not called.  Data-specific
attributes cannot be provided.  All the elements are passed as a
single argument.  For example:

  tr {Don Steve {Really Long Name}}
or
  tr [list Don Steve $reallylongname]

Optional arguments are passed on as row-specific attributes.

**************************************************
BUTTON
**************************************************

cgi_submit_button name=value
cgi_radio_button name=value
cgi_image_button name=value

These procedure create buttons.  The first argument indicates the
variable name and value.  (See notes on "Name-value" commands earlier
to understand behavior of omitted names/values.)  Unless otherwise
mentioned below, additional arguments are passed on as attributes.

  cgi_submit_button "=Submit Form"
  cgi_submit_button "Action=Pay Raise"

  cgi_radio_button "version=1"
  cgi_radio_button "version=2" checked

  cgi_image_button "=http://www.cme.nist.gov/images/title.gif"
  cgi_image_button "Map=http://www.cme.nist.gov/images/msid3.gif"

Groups of radio buttons must share the same variable name.  To address
the obvious question: No, there is no single command to produce a
group of radio buttons because you might very well want to do
arbitrarily-complex calculations in between them.  And with a
long-enough line of buttons, the obvious behavior (laying them all out
in a line like CGI.pm does) makes it hard to tell at a glance if the
buttons associate with the label to the left or the right of them.
Anyway, you'll almost certainly want to write another procedure to
call cgi_radio_button and that can control the variable name.

The radio button argument "checked_if_equal=xxx" indicates that the
current name should be shown selected if it is equal to xxx.  This is
handy if you are creating radio buttons by iterating over a list.

cgi_file_button name

cgi_file_button provides a filename entry box.  When the form is
submitted, the file is "uploaded" (sent from the client to the
server).  The argument enctype=multipart/form-data must be given to
the cgi_form command when using cgi_file_button.

After uploading, the file is the responsibility of the CGI programmer.
In particular, if you do not delete it, it will remain until /tmp is
cleaned up in some other way.

For example, to upload a single file, the form might look like this:

  cgi_form upload height=3 enctype=multipart/form-data {
    cgi_file_button file
    cgi_submit_button =Upload
  }

Uploaded files are automatically made available to the CGI script
using cgi_import_filename.  (See elsewhere for more information.)

cgi_reset_button value

cgi_reset_button creates a a reset button.  An argument overrides the
default label.  For example:

  cgi_reset_button
  cgi_reset_button "Not the Default Reset Button"

cgi_map name cmd
cgi_area args

These procedures are used to specify client-side image maps.  The
first argument of cgi_map is the map name.  The last argument is
evaluated to fill the contents of <map></map> tags.  cgi_area's
arguments are embedded as arguments in an <area> tag.

Warning: These two commands will likely be redefined as I get more
familiar with how they are typically used.

**************************************************
CHECKBOX
**************************************************

cgi_checkbox name=value

cgi_checkbox is similar to cgi_radio_button (see above) except that
multiple values can be checked at the same time.  As explained
earlier, the variable name must end with "List" in order for it to
group all the values as a list in the resulting CGI script.  Other
arguments are passed on as attributes except for the argument
"checked_if_equal=xxx" which indicates that the current name should be
shown selected if it is equal to xxx.  This is handy if you are
creating checkboxes by iterating over a list.

**************************************************
TEXTENTRY AND TEXTAREA
**************************************************

cgi_text name=value

cgi_text provides a one-line text entry box.  It works similarly to
other form elements.  (Read "Name-value commands" elsewhere.)
Additional arguments are passed on as attributes.  Examples:

  cgi_text Foo
  cgi_text Foo=
  cgi_text Foo=value2
  cgi_text Foo=value2 size=5
  cgi_text Foo=value2 size=5 maxlength=10
  cgi_text Foo=value2 size=10 maxlength=5
  cgi_text Foo=value2 maxlength=5

cgi_textarea name=value

cgi_text provides a multiline text entry box.  It works similarly to
other form elements.  (Read "Name-value commands" elsewhere.)
Additional arguments are passed on as attributes.

  set value "A really long line so that we can compare the\
		effect of wrap options."

  cgi_textarea Foo
  cgi_textarea Foo=
  cgi_textarea Foo=$value
  cgi_textarea Foo=$value rows=3
  cgi_textarea Foo=$value rows=3 cols=7
  cgi_textarea Foo=$value rows=3 cols=7 wrap=virtual

**************************************************
SELECT
**************************************************

cgi_select name cmd

cgi_select can be used to produce pull-down menus and scrolled lists.
(And depending upon the future of HTML, I may provide better-named
commands to indicate this.)  Its behavior is controlled by additional
arguments which are simply the appropriate attributes.

cgi_select evaluates cmd which typically contains multiple calls to
cgi_option.

cgi_option string

cgi_option adds options to cgi_select.  By default, the string is
displayed and sent back as the value of the cgi_select variable.  The
value can be overridden by an explicit "value=" argument.  Additional
options are passed on as attributes, except for "selected_if_equal".

"selected_if_equal=xxx" indicates that the current option should be
shown selected if the value is equal to xxx.  This is useful if you
are generating cgi_options in a loop rather than manually.

Here are examples:

  # pull-down menu
  cgi_select Foo {
    cgi_option one selected
    cgi_option two
    cgi_option many value=hello
  }

  # scrolled list, allow multiple selections, show all elements
  cgi_select FooList multiple {
    cgi_option one selected
    cgi_option two selected
    cgi_option many 
  }

  # scrolled list, allow multiple selections, show 2 elements max
  cgi_select FooList multiple size=2 {
    cgi_option one selected
    cgi_option two selected
    cgi_option many 
  }

  # choose "selected" dynamically
  # example: list all Tcl command and select "exit" automatically
  cgi_select FooList multiple size=5 {
    foreach o [info comm] {
      cgi_option $o selected_if_equal=exit
    }
  }

Note: If both value= and selected_if_equal= appear, the test for
selection is made against the last value string (implicit or explicit)
that appears before the selected_if_equal argument.  In other words,
if you want selected_if_equal= to be tested against the explicit
value= argument, put the selected_if_equal= *after* the value=.

**************************************************
APPLET
**************************************************

cgi_applet parameters cmd

cgi_applet produces <applet></applet> tags such as for Java.

cgi_param name=value

cgi_param produces <param> tags for passing parameters to applets.

For example:

  cgi_applet codebase="../" code="some.class" width=640 height=480 {
     cgi_param parm=value
  }

**************************************************
PLUG-IN
**************************************************

cgi_embed src widthxheight

cgi_embed creates an <embed> tag.  The first argument is the source.
The second argument is the width and height in the style "WxH".
Optional arguments are passed on to the tag.  For example:

  cgi_embed myavi.avi 320x200 autostart=true

produces:

  <embed src="myavi.avi" width="320" height="200" autostart=true>

Notice the autostart value is unquoted because autostart is not
specifically defined by the spec.  The argument "-quote" causes all
remaining attributes to be url encoded and quoted.  For example:

  cgi_embed myavi.avi 320x200 a=b -quote c=d e=f

produces:

  <embed src="myavi.avi" width="320" height="200" a=b c="d" e="f">

**************************************************
MISC
**************************************************

cgi_hr

cgi_hr produces horizontal rules.  Optional arguments are passed on as
attributes.

**************************************************
COMMENTS
**************************************************

cgi_comment stuff

cgi_comment can comment out anything including blocks of code.

cgi_html_comment stuff

cgi_html_comment comments out things in such a way that the comment
appears in the final html itself.

**************************************************
OUTPUT
**************************************************

cgi_put string

cgi_put prints the string with no new terminating newline.  This is
simply a shorthand for puts -nonewline.

cgi_puts

Many routines in this library send output to the standard output by
default.  This is convenient for CGI scripts.  However, if you want to
generate multiple files, it is useful to be able to redirect output
dynamically.  Output can be redirected by redefining cgi_puts.  The
default definition of cgi_puts is:

  proc cgi_puts {args} {
    eval puts $args
  }

cgi_puts must allow for an optional -nonewline argument.  For example,
here is a definition that writes to a file identified by the global
"fd".

  proc cgi_puts {args} {
    global fd

    puts -nonewline $fd [lindex $args end]
    if {[llength $args] > 1} {
      puts $fd ""
    }
  }

cgi_buffer cmd

cgi_buffer evaluates its argument in such a way that output (through
explicit or implicit calls to cgi_puts) is not produced.  Instead, the
output is returned.

For example, the following cmd generates a link with the hyperlinked
portion being a header and two paragraphs.

  link tag [cgi_buffer {
    h3 "Level 3 header"
    p "New paragraph"
    p "Another paragraph"
  }] $URL

cgi_buffer can be called recursively.

cgi_buffer_nl string

By default, cgi_buffer generates newlines at the end of every line in
the style of puts.  It is occasionally useful to be able to disable
this - for example, when calling it inside cgi_preformatted.  The
newline definition can be changed via cgi_buffer_nl.  (There is no
point to redefining cgi_puts since cgi_buffer doesn't use it.)  A null
argument suppresses any newline.  For example:

  cgi_buffer_nl ""

cgi_buffer_nl returns the previous definition.

**************************************************
MAIL
**************************************************

Rudimentary email support is provided, in part, because it is useful
for trapping errors - if debugging is disabled (i.e., during actual
use) and an error is encountered, errors are emailed to the service
admin.

The current implementation only permits one email transaction at a
time.

cgi_mail_addr addr

cgi_mail_addr defines the email address that mail comes from.  Your
email system must allow this, of course.  (If your system doesn't
allow it, the request is usually ignored.)

cgi_mail_start addr

cgi_mail_start creates a mail message to be delivered the given addr.
cgi_mail_add should be used to provide a subject and body.

cgi_mail_add string

cgi_mail_add adds strings to the current mail message.  No argument
causes a blank line to be added.

cgi_mail_end

cgi_mail_end queues the the current mail message for delivery.

  cgi_mail_start libes@nist.gov
  cgi_mail_add "Subject: [cgi_name] request succeeded
  cgi_mail_add
  cgi_mail_add "Your request has been processed."
  cgi_mail_add "Thanks for using [cgi_name].
  cgi_mail_end

cgi_mail_relay host

cgi_mail_relay identifies a host to be used for mail relay services.
(This is currently only used when sendmail support is not available.)
If a relay is not defined, email is sent directly to the recipient.
