cgi.tcl reference

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 &amp 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

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 url="foo.gif" alt="Foo's Bar & 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).

#### 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_filename flag name`

> 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 only if you are using the Expect extension. If you are using 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.

    code                    Returns
    cgi_lt                  &lt;
    cgi_gt                  &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.

`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 "\<". 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.