## mod_dtcl Installation

1. Check dependencies
   To install mod_dtcl, you will need Tcl 8.2 or greater and Apache 1.3.xx. It is known to run on Linux, FreeBSD, OpenBSD, and Solaris and HPUX. NT is also possible - please see the directions in the distribution.
2. Get mod_dtcl
   If you are running a Debian or FreeBSD system, there are pre-built packages available at: http://www.debian.org/Packages/unstable/web/libapache-mod-dtcl.html or http://www.freebsd.org/cgi/ports.cgi?query=mod_dtcl.
   Otherwise, download the sources at http://tcl.apache.org/mod_dtcl/download/.
3. Uncompress the sources
   `gunzip apache-1.3.X.tar.gz
   tar -xvf apache-1.3.X.tar.gz
   ` You don't need the Apache sources if you are building a shared object module. You do, however, need the header files. Some systems, such as Debian GNU/Linux, provide these independently - otherwise, you probably still need the sources.
   `gunzip mod_dtcl-X.X.X.tar.gz
   tar -xvf mod_dtcl-X.X.X.tar.gz
   `
4. Configuring, builddtcl.sh, etc...
   Do you want to build mod_dtcl as a shared object (such as a .so file on Linux, or a .dll on windows), or compile it directly as a part of the Apache executable? The Apache Software Foundation has put together a nice manual which explains things in detail.
   - For shared objects
     `cd ../mod_dtcl/
     ` Edit the `builddtcl.sh` script. The 3 variables you may need to change are:
     - `TCLSH`
       Name of the tclsh program on your computer.
     - `APACHE`
       Location of the Apache sources (for static builds only).
     - `INC`
       Location of the Apache headers (you will need this even for building shared objects).
     `./builddtcl.sh shared`
     `cp mod_dtcl.so /usr/lib/apache/wherever/the/other/shared/objects/reside` For shared object builds, you need to copy the object into the directory where the other shared objects are kept for your Apache build. On Debian GNU/Linux systems, for instance, this is in `/usr/lib/apache/1.3/`.
   - For static builds
     `cd apache-1.3.X/
     ./configure
     ` `cd ../mod_dtcl/
     ` Edit the `builddtcl.sh` script. The 3 variables you may need to change are:
     - `TCLSH`
       Name of the tclsh program on your computer.
     - `APACHE`
       Location of the Apache sources (for static builds only).
     - `INC`
       Location of the Apache headers (you will need this even for building shared objects).
     `./builddtcl.sh static`
     `./builddtcl.sh install`
     `cd ../apache-1.3.X
     ` `./configure --activate-module=src/modules/mod_dtcl/mod_dtcl.a [ other configure options ]
     ` `export EXTRA_LIBS="-ltcl8.X -lm"`
     `make -e
     ` `make install
     `
5. Configure Apache
   - http.conf
     `LoadModule dtcl_module /usr/lib/apache/1.3/mod_dtcl.so`
     This points Apache to the shared object if mod_dtcl is being used as a loadable module.
   - srm.conf
     `AddType application/x-httpd-tcl .ttml`
     `AddType application/x-dtcl-tcl .tcl` (optional)
     These add the .ttml and .tcl (if desired) types to Apache, so that they are processed by mod_dtcl.

## mod_dtcl Apache directives

- `Dtcl_Script GlobalInitScript "script"`
  Tcl script that is run when each interpreter is initialized. `"script"` is actual Tcl script, so to run a file, you would do `Dtcl_Script GlobalInitScript "source /var/www/foobar.tcl"`.
- `Dtcl_Script ChildInitScript "script"`
  Script to be evaluated when each apache child is initialized. This is the best place to load modules.
- `Dtcl_Script ChildExitScript "script"`
  Script to be evaluated when each apache child exits.
- `Dtcl_Script BeforeScript "script"`
  Script to be evaluated before each .ttml page. Note that you cannot use `hputs` in the BeforeScript, but must instead use `buffer_add`.
- `Dtcl_Script AfterScript "script"`
  Script to be called after each .ttml page.
- `Dtcl_Script ErrorScript "script"`
  This code is called in place of the standard 'error' pages generated for mod_dtcl. This directive may be useful if you have sensitive logic that you wish to protect.
- `Dtcl_CacheSize cachesize`
  Number of ttml scripts to cache as Tcl Objects. Default is MaxRequestsPerChild / 2, or 50, if MaxRequestsPerChild is 0.
- `Dtcl_UploadFilesToVar on/off`
  If on, files will be uploaded to the variable UPLOAD(data). Be careful with this, as large files could use up your memory.
- `Dtcl_SeperateVirtualInterps on/off`
  If on, each VirtualHost will have its own Tcl interpreter.

## mod_dtcl specific Tcl commands and variables

- `buffer_add string`
  Add text to output_buffer for later printing. Used internally.
- `hputs ?-error? text`
  The mod_dtcl version of "puts". Outputs to the client, instead of to stdout. The error option permits you to send an 'error message' to the apache log file, at the NOTICE level.
- `var`
  These commands retrieve or retrieve information about "CGI" variables that are passed to the dtcl script via GET or POST operations.
- `var get varname`
  Returns the value of variable 'varname' as a string (even if there are multiple values).
- `var list varname`
  Returns the value of variable 'varname' as a list, if there are multiple values.
- `var exists varname`
  Returns 1 if varname exists, 0 if it doesn't.
- `var number`
  Returns the number of variables.
- `var all`
  Return a list of variable names and values.
- `upload`
  These commands retrieve or retrieve information about files that have been uploaded to the server. They replace the `UPLOAD` variable.
- `upload get varname channel`
  Returns a Tcl channel that can be used to access the uploaded file.
- `upload get varname save name`
  Moves the uploaded file to the give name.
- `upload get varname data`
  Returns data uploaded to the server. This is binary clean.
- `upload info varname exists`
  Returns 1 if the variable exists, 0 if not.
- `upload info varname size`
  Returns the size of the file uploaded.
- `upload info varname type`
  If the Content-type is set, it is returned, otherwise, an empty string.
- `upload info varname filename`
  Returns the filename on the remote host that uploaded the file.
- `upload names`
  Returns the variable names, as a list, of all the files uploaded.
- `hgetvars`
  Get environmental, and Cookie variables. This is in a seperate command so as not to make the server do this every time you load a .ttml file. `ENVS` and `COOKIES` are the associative arrays created. `ENVS` contains environmental variables, and `COOKIES` contains any cookies recieved from the client.
- `include filename`
  Include a file without parsing it. This is the best way to include an HTML file or any other static content.
- `parse filename`
  "Source" a .ttml file. This is the way to include other .ttml files.
- `hflush`
  Flush the output buffers to the client. Use this if you want to incrementally update a page.
- `headers redirect uri`
  Redirect from the current page to a new URI. Must be done in the first block of TCL code.
- `headers setcookie -name cookie-name -value cookie-value ?-expires date/time? ?-domain domain? ?-path path? ?-secure?`
  This command is for setting cookies. Cookie-name is the name of the cookie, cookie-value is the data associated with the variable. Expires sets an expiration date for the cookie, and must be in the format 'DD-Mon-YY HH:MM:SS', path sets the path for which the cookie is valid, and secure specifies that the cookie is only to be transmitted if the connection is secure (HTTPS).
- `headers type content-type`
  This command sets the "Content-type:" header returned by the script, which is useful if you wish to create a PNG (image), for example, with mod_dtcl.
- `headers set headername value`
  Set arbitrary header names and values.
- `makeurl filename`
  Create a self referencing URL from a filename. For example: `makeurl /tclp.gif` returns http://[hostname]:[port]/tclp.gif.
- `dtcl_info`
  Prints information on the internals of the module in HTML. Currently, only the PID and size of the object cache are reported.

## Other mod_dtcl Documentation

### Internals

- Read the code!
- Initialization
  When Apache is started, (or when child Apache processes are started if a threaded Tcl is used), `tcl_init_stuff` is called, which creates a new interpreter, and initializes various things, like the `apache_channel` channel system. The caching system is also set up, and if there is a GlobalScript, it is run.
- Achan/apache_channel
  The "Apache Channel" system was created so that it is possible to have an actual Tcl channel that we could redirect standard output to. This lets us use, for instance, the regular "puts" command in .ttml pages. It works by creating commands that write to memory that is slated to be sent to the client.
- Page parsing/execution
  In `send_parsed_file` Each .ttml file is loaded and run within its own namespace. No new interpreter is created for each page. This lets you share variables, and most importantly, loaded modules, from a common parent (such as one of the InitScripts). When a file is loaded, it is transformed into a Tcl script by putting everything outside of <? and ?> into large hputs statements. When the script is complete, it is then inserted into the cache, for future use. In fact, if the file modification information doesn't change, mod_dtcl will execute the cached version of the script the next time it is encountered.
- Binary data
  mod_dtcl is capable of outputing binary data, such as images, or loading binary data with 'include'.

### Upgrading From Older (< 0.9.3) Versions

- New tags
  As of version 0.9.4, mod_dtcl uses <? and ?> instead of <+ and +> to delimit sections of Tcl code. By default, dtcl is still compiled with code to parse the <? ?> tags, but it will run faster if `USE_OLD_TAGS` is set to 0 in `mod_dtcl.h`. You can automatically change your .ttml files to the new format by using the `newtags.sh` script in the contrib/ directory. Run it at the top level of your DocumentRoot.
- headers setcookie
  The `headers setcookie` command now uses the `-name` and `-value` flags for those arguments, whereas this was not necessary in the past.