diff options
author | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
---|---|---|
committer | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
commit | 094ca96844842928810f14844413109fc6cdd890 (patch) | |
tree | e60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /web/src/cgi.tcl-1.10/doc | |
download | alpine-094ca96844842928810f14844413109fc6cdd890.tar.xz |
Initial Alpine Version
Diffstat (limited to 'web/src/cgi.tcl-1.10/doc')
-rw-r--r-- | web/src/cgi.tcl-1.10/doc/ref.txt | 1651 |
1 files changed, 1651 insertions, 0 deletions
diff --git a/web/src/cgi.tcl-1.10/doc/ref.txt b/web/src/cgi.tcl-1.10/doc/ref.txt new file mode 100644 index 00000000..79ddd721 --- /dev/null +++ b/web/src/cgi.tcl-1.10/doc/ref.txt @@ -0,0 +1,1651 @@ +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 { + p [cgi_img foo.gif "alt=Foo's Bar & Grill"] + } + +This is translated to + + <body bgcolor="#123456"> + <p><img src="foo.gif" alt="Foo's Bar & Grill"></p> + </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 return 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. + +If an error is caught when debugging is enabled, the diagnostic is +anchored with #cgierror. This is useful in scripts that produce +voluminous output. + +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 + + +************************************************** +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. +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. + +If cgi_input encounters multiple values for variables that do not end +with List, it will provide the values in a Tcl-style list. However, +this leaves an ambiguity in the case of a single value that "looks" +like a list, such as "a b". Although a form author can usually "know" +whether a string is a list or not, it is simpler to stick to the +convention stated earlier. + +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, files, and cookies. + +-- Variables and Cookies + +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. + +-- Files + +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. + +cgi_file_limit files chars + +cgi_file_limit establishes limits on the number of files and their +size. This is provided to prevent denial of service attacks. If the +limit is exceeded, an error is raised from within cgi_input. + +Note that when the limit is exceeded, cgi_input fails immediately. So +if you just want to check file sizes that are not security related - +for example, you just want to accept gifs under 10K - it's better to +accept the gifs and then check the size manually (i.e., [file size +...]. That way, cgi_input will completely read all the variables and +you can give more appropriate diagnostics. + +The default limit is 10 100MB files. If you were to set this +yourself, it would look this way: + +cgi_file_limit 10 100000000 + + +-- File 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]} + } + file delete $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.) + +************************************************** +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=1 + + 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 +button should be shown selected if its associated value is xxx. This +is handy if you are creating radio buttons by iterating over a list. + +The radio button "checked=value" indicates that the button should be +shown selected if the value is a boolean of value true. + +All other arguments are passed on as attributes. + +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. + +The argument "checked_if_equal=xxx" which indicates that the current +name should be shown selected if its associated value is xxx. This is +handy if you are creating checkboxes by iterating over a list. + +The argument "checked=value" indicates that the checkbox should be +shown selected if the value is a boolean of value true. + +Other arguments are passed on as attributes. + + +************************************************** +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_textarea 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. + +************************************************** +INITIALIZATION +************************************************** + +cgi_init + +The package initializes itself upon initial loading, however it can be +explicitly initialized by calling cgi_init. This is useful in +environments such as tclhttpd. |