|1Server Side Includes (SSI)|| |^ The HTML pre-processor is used to provide dynamic information inside of an otherwise static, HTML (HyperText Markup Language) document. The HTTPd server provides this as internal functionality, scanning the input document for special pre-processor |/directives||, which are replaced by dynamic information based upon the particular directive. |^ As of version 5.1 WASD SSI has been enhanced to provide flow-control statements, allowing blocks of the document to be conditionally processed, see |link|Flow Control||. These extensions allow quite versatile documents to be created without resorting to script processing. |^ Two documents are provided as examples of SSI processing. |bullet| |item| |*A simple SSI document.| |table| |~ |. |link%|/wasd_root/wasdoc/env/ssi.shtml?httpd=content&type=text/plain|\ WASD_ROOT:[WASDWASDOC.ENV]SSI.SHTML| |. (|link%|/wasd_root/wasdoc/env/ssi.shtml|access as SSI||) |!table| |item| |*An SSI document using variable assignment and flow-control.| |table| |~ |. |link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=content&type=text/plain|\ WASD_ROOT:[WASDWASDOC.ENV]XSSI.SHTML| |. (|link%|/wasd_root/wasdoc/env/xssi.shtml|access as SSI||) |!table| |!bullet| |^ By default the HTML pre-processor is invoked when the document file's extension is ".SHTML". As there is a significant overhead with pre-processed HTML compared to normal HTML, it should only be used when it serves a useful documentary purpose, and not just for the novelty. |^ Essential compatibility with OSU Server Side Includes is provided. This may ease any transition between the two. See |link|OSU Compatibility|| for further information. |2Virtual Documents| |^ One effective use for pre-processed HTML is the creation of single virtual documents from two or more physical documents. That is, the pre-processed document is used to include multiple physical documents, that may even be independently administered, to return a composite document to the client. This is a relatively low-overhead activity as SSI goes, but because it is a dynamic document, without some extra considerations (see |link|Last Modified Information||). |0Example 1|| |^ This provides an example of the efficient use of SSI processing to create virtual documents. Each page will comprise a header (containing the body tag and page header, etc), the document proper and a footer (containg the end-of-page information, modification date, and end-body tag, etc). |code| Just an example!

This is the document information.

Blah, blah, blah. |!code| |^ A more efficient variant places the document proper in its own, plain HTML file which is then #included (it is much, much, much more efficient for the server to |/throw| a file at the network, than parse every character in one ;^) |code| Just an example! |!code| |0Example 2|| |^ This example provides a seemingly more convoluted, but very much more powerful configuration, that uses recursion to greatly simplify maintenance of common-layout documents for the end-user. |^ File 1; the document accessed via the browser URL, doesn't matter what its name is, this configuration is completely naming independent. |code| |!code| |^ File 2; the TEMPLATE.SHTML refered to by the first include above. |code| |!code| |^ File 3; the DOCUMENT.HTML refered to by the second include in file 1. |^ This is just a |*bunch of HTML||! |^ |*This is an explanation of how it works |...||| |number#| |item| the browser accesses file 1 via a URL |item| processing begins with file 1 |item| file 1 checks if it has a parent (is the first file processed), |^- |*it doesn't and so |...||| |item| file 1 set a variable named TITLE |item| file 1 #includes file 2, a site-common template |item| file 2 substitutes the TITLE variable contents as the document title |item| file 2 #includes a site-common header |item| file 2 #includes an optional document-local header |item| |*here's the interesting bit |...||| |^- file 2 now re-#includes the original document, file 1 (!!) |item| file 1 checks if it has a parent (is the first file processed), |^- |*it does and so |...||| |item| file 1 #includes file 3 (the actual contents of the document) |item| file 3 is a plain HTML document, just added to the output |item| file 1 is now exhausted and processing returns to file 2 |item| file 2 #includes an optional document-local footer |item| file 2 #includes a site-common footer |item| file 2 is exhausted and processing returns to file 1 |item| file 1 is exhausted and processing stops |!number| |^ The following link provides an example of a |link%|/wasd_root/wasdoc/env/example_document.shtml|such a virtual document||. |2Last-Modified Information| |^ SSI documents generally contain dynamic elements, that is those that may change with each access to the document (e.g. current date/time). This makes evaluation of any document modification date difficult and so by default no "Last-Modified: |/timestamp||" information is supplied against an SSI document. The potential efficiencies of having document timestamps, so that requests can be made for a document to be returned only if modified after a certain date/time ("If-Modified-Since: |/timestamp||"), are significant against the CPU overheads of processing SSI documents. |^ WASD allows the document author to determine whether or not a last-modified header field should be generated for a particular document and which contributing file(s) should be used to determine it. This is done using the #modified directive. If a virtual document is made up of multiple source documents (files) each can be assessed using multiple virtual= or file= tags, the most recently modified will be used to determine if the virtual document has been modified, and also to generate the last-modified timestamp. |^ The |/if-modified-since|| tag compares the determined revision date/time of the document file(s) with any "If-Modified-Since:" timestamp supplied with the request. If the virtual document's revision date/time is the same or older than the request's then a not-modified (304 status) header is generated and sent to the client and document processing ceases. If more recent an appropriate "Last-Modified:" header field is added to the document and it continues to be processed. |^ If a request has a "Pragma: no-cache" field (as with Navigator's |/reload|| function) the document is always generated (this is consistent with general WASD behaviour). The following example illustrates the essential features. |code| |!code| |^ This construct should be placed at the very beginning of the SSI document, and certainly before there is any chance of output being sent to the browser. Once output to the client has occured there can be no change to the response header information (not unreasonably). |2Pre-Expiring Documents| |^ SSI preprocessed documents are |/dynamic|| in the sense that the information presented can be different every time the document is generated (e.g. if time directives are included). If it is important that each time the document is accessed it is regenerated then an HTML META tag can be included in the HTML header to cause the document to |/expire||. This will result in the document being reloaded with each access. This can be accomplished two ways. |bullet| |item| Use the #modified directive to include an "Expires: |/timestamp||" response header field. Place the following construct at the beginning of the SSI document. |code| |!code| An alternative, if the objective to to pre-expire the document, is to specify an expiry of zero. The is specially handled by the SSI engine. It adds an expiry response header field, plus cache-control header fields to suppress document caching (on compliant browsers). |code| |!code| |!bullet| |2Directive Syntax| |^ The syntax follows closely that used by the other implementations, but some directives are tailored to the WASD and VMS environment. The directive is enclosed within an HTML comment and takes the form: |code| |!code| |^ A |/tag|| provides parameter information to the directive. A directive may have zero, one or more parameters. Values supplied with any tag may be literal or via variable substitution (see |link|Variables||). A value must be encolosed by quotation marks if it contains white-space. |^ A directive |*can be split over multiple lines|| provided the new line begins naturally on white-space within the directive. For example, this is correctly split |code| |!code| while the following is not (and would produce an error) |code| |!code| |^ Directive and tag keywords are case insensitive. The tag value may or may not be case sensitive, depending upon the command/tag. Generally the effect of a command is to produce additional text to be inserted in the document, although it is possible to control the flow of processing in a document with decision structures. |2Directives| |0SSI Directives| |table| |~_ |: Directive|: Description|: Section |~ |~#* |. #accesses |. document access count |. |link|Accesses| |~ |. #config |. document processing options |. |link|Config| |~ |. #dir |. directory listing |. |link|Dir| |~ |. #dcl |. DCL command processing |. |link|DCL| |~ |. #echo |. output information |. |link|echo| |~ |. #elif |. flow control |. |link|elif| |~ |. #else |. flow control |. |link|else| |~ |. #endif |. flow control |. |link|endif| |~ |. #exec |. same as "#dcl" |. |link|exec| |~ |. #exit |. flow control, stop current document processing |. |link|exit| |~ |. #fcreated |. output file creation date/time |. |link|fcreated| |~ |. #flastmod |. output file last modification date/time |. |link|flastmod| |~ |. #fsize |. output file size |. |link|fsize| |~ |. #if |. flow control |. |link|if| |~ |. #include |. include a text file or another SSI document |. |link|include| |~ |. #modified |. HTTP response control |. |link|modified| |~ |. #orif |. flow control |. |link|orif| |~ |. #printenv |. list document variables |. |link|printenv| |~ |. #set |. assign value to a document variable |. |link|set| |~ |. #ssi |. block of SSI statements |. |link|ssi| |~ |. #stop |. stop SSI processing completely |. |link|stop| |!table| |3.#ACCESSES| |^ The |/.#accesses|| directive allows the number of times the document has been accessed to be included. It does this by creating a counter file in the same location and using the same name with a dollar symbol appended to the type (extension). The count may be reset by deleting the file. This is an expensive function (in terms of file system activity) and so should be used appropriately. It can be disabled by server configuration. Three tags provide additional functionality: |bullet| |item| |*ORDINAL| |code| |!code| |^ Provides the count as 1st, 2nd, 3rd, 4th, 5th |...| 10th, 11th, 12th |...| 120th, 121st, 122nd, etc. |item| |*SINCE| |code| |!code| |^ This tag includes the specified text immediately after the access count is displayed, then adds the creation date of the counter file. |item| |*TIMEFMT| |code| |!code| Allows the time format of the |/since|| tag to be supplied, where |/time-format|| is specified according to |link|Time Format||. |!bullet| |3.#CONFIG| |^ The |/.#config| directive allows time and file size formats to be specified for all subsequent directives providing these values. Optional specifications for individual directives may still be made, and override, do not supercede, any specification made using a |/config| directive. A |/config| directive may be made once, or any number of times in a document, and applies until another is made, or until the end of the document. |bullet| |item| |*ERRMSG| |code| |!code| |^ This directive allows the error message generated if a problem problem processing the SSI document occurs (e.g. miss-spelled directive) to be specified in the document. |item| |*TIMEFMT| |code| |!code| Where |/time-format|| is specified according to|link|Time Format||. |item| |*SIZEFMT| |code| |!code| Where |/size-format| is specified using the following keywords: |bullet#| |item| "abbrev" (as bytes, kbytes, Mbytes) |item| "blocks" (VMS blocks, used) |item| "bytes" (e.g. "1,256,731 bytes") |!bullet| |item| |*TRACE| |code| |!code| |^ Switches document processing trace on or off, intended for use when debugging more complex or flow-controlled SSI documents. |^ Output from a trace is colour-coded. |bullet| |item| |*Blue |-| | As a line is read from the document is is displayed in blue. The text is preceded by a square-bracketed source file line number and flow-control level. |item| |*Red |-| | As an SSI statement is actually processed it is displayed in red. Due to document parsing this may occur at some point after the line is read from file. |item| |*Magenta |-| | As variables are set or read the variable name and value is displayed. A variable set has the name separated from the value by an equate symbol ("="), when being read the character is a full-colon (":"). |item| |*Black |-| | Document (HTML and text) output is displayed as black plain text. |!bullet| |^ The following link provides an example of a |link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=ssi&trace=on|document trace||. |!bullet| |3.#DIR| |^ The |/.#dir| directive generates an |/Index of |...||| directory listing inside an HTML document. Apart from not generating a title (it is up to the pre-processed document to title, or otherwise caption, the listing) it provides all the functionality of the WASD HTTPd directory listing (see |link|Directory Listing||), including query string format control via the "par=" parameter (note that from the "?httpd=index" introducer used with directory listings is not necessary from SSI). It is an WASD HTTPd extension to pre-processed HTML. |bullet| |item| |*FILE| |^ Listing specified using a VMS file path. |code| |!code| |item| |*VIRTUAL| |^ Listing specified using URL-style syntax. |code| |!code| |!bullet| |^ For example: |code| |!code| |3.#DCL| |^ The |/.#dcl| directive executes a DCL command and incorporates the output into the processed document. It is an WASD HTTPd extension to the more common |/exec| directive, which is also included. |^ By default, output from the DCL command has all HTML-forbidden characters (e.g. "<", "&") escaped before inclusion in the processed document. Thus command output cannot interfere with document markup, but nor can the DCL command provide HTML markup. This behaviour may be changed by appending the following tag to the directive: |code| type="text/html" |!code| |^ Some |/.#dcl| directives are for |/privileged| documents only, documents defined as those being owned by the SYSTEM account, and not being world-writeable. The reason for this should be obvious. There are implicit security concerns about any document being able to execute any DCL command(s), even if it is being executed in a completely unprivileged process. Hence only |/innocuous| commands are allowed in standard documents. |bullet| |item| |*SAY| |^ Execute the DCL "WRITE SYS$OUTPUT" command, using the specified parameter. |code| |!code| |item| |*SHOW| |^ Execute the DCL "SHOW" command, using the specified parameter. |code| |!code| |item| |*DIR| |^ Execute the DCL "DIRECTORY" command, using the supplied file specification. Qualifiers may be included in the optional "par" tag to control the format of the listing. |code| |!code| |item| |*EXEC| (privileged) |^ Execute the specified DCL command. |code| |!code| |item| |*FILE| (privileged) |^ Execute the DCL command procedure specified as a VMS file path, with any specified parameters applied to the procedure. |code| |!code| |item| |*VIRTUAL| (privileged) |^ Execute the DCL command procedure specified in URL-style syntax, with any specified parameters applied to the procedure. |code| |!code| |item| |*CGI| |^ Execute the specified CGI script. The CGI response header is suppressed and only the response body is included in the document. |code| |!code| |!bullet| |3.#ECHO| |^ The |/.#echo| directive incorporates the specified information into the processed document. Multiple tags may be used within the one directive. |bullet| |item| |*VALUE=| |^-|*VAR=| |^ Any SSI variable (e.g. CREATED), CGI variable (e.g. HTTP_USER_AGENT), or document assigned variable (e.g. EXAMPLE1), see |link|Variables||. |code| |!code| |item| |*CREATED| |^ The date/time of the current document's creation. |code| |!code| |item| |*DATE_LOCAL| |^ Include the current date/time. |code| |!code| |item| |*DATE_GMT| |^ Include the current Greenwich Mean Time (UTC) date/time. |code| |!code| |item| |*DOCUMENT_NAME| |^ The current document's URL-style path. |code| |!code| |item| |*FILE_NAME| |^ The current document's VMS file path. |code| |!code| |item| |*HEADER| |^ Append the specified string to the response header (with correct carriage control). Should be used as early as possible in the SSI document. |code| |!code| |item| |*LAST_MODIFIED| |^ The date/time of the current document's last modification. |code| |!code| |!bullet| |3.#ELIF| |^ The |/.#elif| directive (else-if) allows blocks of HTML markup and SSI directives to be conditionally processed, see |link|Flow Control|| and |link|if||. This directive effectively allows a |/case| statement to be constructed. |code| |!code| |3.#ELSE| |^ The |/.#else| directive allows blocks of HTML markup and SSI directives to be conditionally processed, see |link|Flow Control||. It is the default block after an "#if", "#orif" or "#elif". |code| |!code| |3.#ENDIF| |^ The |/.#endif| directive marks the end of a block of document text being conditionally processed, see |link|Flow Control||. |code| |!code| |3.#EXEC| |^ The |/.#exec| directive executes a DCL command and incorporates the output into the processed document. It is the VMS equivalent of the |/exec| shell directive of some Unix implementations. It is implemented in the same way as the #DCL directive, and so the general detail of that directive applies. It supports both the |/cmd| tag and the |/cgi| tag, allowing execution of CGI scripts (the response header is absorbed). |code| |!code| |^ The |/.#exec| directive is for |/privileged| documents only, documents defined as those being owned by the SYSTEM account, and not being world-writeable. The reason for this should be obvious. There are implicit security concerns about any document being able to execute any DCL command(s), even if it is being executed in a completely unprivileged process. |3.#EXIT| |^ The |/.#exit| directive causes the server to stop processing the current SSI file. If the current file was an #included SSI file, processing continues back with the parent file. Note that the |/.#stop| directive also is available, it stops processing of the entire virtual document. |code| |!code| |3.#FCREATED| |^ The |/.#fcreated| directive incorporates the creation date/time of a specified file/document into the processed document. |bullet| |item| |*FILE| |^ Document specified using a VMS file path. |code| |!code| |item| |*VIRTUAL| |^ Document specified using URL-style syntax. |code| |!code| |!bullet| |3.#FLASTMOD| |^ The |/.#flastmod| directive incorporates the last modification date/time of a specified file/document into the processed document. |bullet| |item| |*FILE|| |^ Document specified using a VMS file path. |code| |!code| |item| |*VIRTUAL|| |^ Document specified using URL-style syntax. |code| |!code| |!bullet| |3.#FSIZE| |^ The |/.#fsize|| directive incorporates the size, in bytes, kbytes or Mbytes, of a specified file/document into the processed document. |bullet| |item| |*FILE| |^ Document specified using a VMS file path. |code| |!code| |item| |*VIRTUAL| |^ Document specified using URL-style syntax. |code| |!code| |!bullet| |3.#IF| |^ The |/.#if| directive allows blocks of HTML markup and SSI directives to be conditionally processed, see |link|Flow Control||. |bullet| |item| |*VAR=| |^ Variable the decision will be based upon. |code| |!code| |item| |*EQS=| |^ Is the string the same as in the variable? |item| |*EQ=| |^ If the variable is a number is it the same as this? |item| |*GT=| |^ If the variable is a number is it greater than this? |item| |*LT=| |^ If the variable is a number is it less than this? |item| |*SRCH=| |^ Search the variable for this string. May contain the |=.*| (asterisk) wildcard, matching one or more characters, and the |*.%| (percentage), matching any single character. |!bullet| |^ As in the following examples: |code| |!code| |3.#INCLUDE| |^ The |/.#include| directive incorporates the contents of a specified file/document into the processed document. |bullet| |item| |*FILE| |^ Include the contents of the document specified using a VMS file specification. |code| |!code| |item| |*VIRTUAL| |^ Include the contents of the document specified using URL-style syntax. |code| |!code| |!bullet| |^ The contents of the specified file are included differently depending on the MIME content-type of the file. Files of |/text/html| content-type (HTML documents) are included directly, and any HTML tags within them contribute to the markup of the document. Files of |/text/plain| content-type (plain-text documents) are encapsulated in "

" tags and have all HTML-forbidden
characters (e.g. "<", "&") escaped before inclusion in the processed document. 
An HTML file can be forced to be included as plain-text by using the following
syntax:

|code|

|!code|

|^ To "force" a file to be considered as text regardless of the actual content
(as determined by the server from the file type), use on of the following
depending on whether it should be rendered as plain or HTML text.

|code|


|!code|

|^ Other SSI files may be included and their content dynamically included in
the resulting document.  To prevent a recursive inclusion of documents the
nesting level of SSI documents is limited to five.
 
|3.#MODIFIED|

|^ The |/.#modified| directive allows a document author to control the
"Last-Modified:"/"If-Modified-Since:"/"304 Not modified" behaviour of an SSI
document.  See |link|Virtual Documents||.

|bullet|

|item| |*/no tag|

|^ Get the last-modified date/time of the current document.

|code|

|!code|

|item| |*FILE|

|^ Get the last-modified date/time of the document specified using VMS file
specification.

|code|

|!code|

|item| |*VIRTUAL|

|^ Get the last-modified date/time of the document specified using URL-style
syntax.

|code|

|!code|

|item| |*IF-MODIFIED-SINCE|

|^ Compares any "If-Modified-Since:" request header timestamp to the revision
date time obtained using |/file| or |/virtual| (most recent if multiple).  If
the document timestamp is more recent (has been modified) an appropriate
"Last-Modified" response header field is generated and added to the response,
and document processing continues.  If it has not been modified a "304"
response header is return (document not modified) and document processing
stops.

|code|

|!code|

|item| |*LAST-MODIFIED|
|^ Adds a "Last-Modified:" response header field using a timestamp retrieved
using |/file| or |/virtual| (note: unnecessary if the |/if-modified-since| tag
is used).

|code|

|!code|

|item| |*EXPIRES|

|^ Adds a "Expires:" response header field.  The string literal should be a legitimate RFC-1123 date string.  This can be
used for pre-expiring documents (so they are always reloaded), set it to a date
in the not-too-distant past (as in the example below). Of course it could also
be used for setting the legitimate future expiry of documents.

|code|

|!code|

|!bullet|

|3.#ORIF|

|^ The |/.#orif| directive (or-if) allows blocks of HTML markup and SSI
directives to be conditionally processed, see |link|Flow Control| and
|link|if||.  In the absence of any real expression parser this directive allows
a block to be processed if one of multiple conditions are met.

|code|

|!code|
 
|3.#PRINTENV|

|^ The |/.#printenv| directive prints a plain-text list of all SSI-specific,
then CGI, then document-assigned variables (see |link|Variables||). This
directive is intended for use when debugging flow-controlled SSI documents.

|code|

|!code|

|^ The following link uses the example SSI document
|link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=ssi&text=plain|\
WASD_ROOT:[WASDOC.ENV]XSSI.SHTML| to
|link%|/wasd_root/wasdoc/env/xssi.shtml|demonstrate| this.

|3.#SET|

|^ The |/.#set| directive allows a user variable to be assigned or modified,
see |link|Variables||.

|code|

|!code|

|^ Variables are always stored as strings and have a finite but generally
usable length.  Some comparison tags provided in the flow-control directives
treat the contents of variables as numbers.  A numeric conversion is done at
evaluation time.
 
|3.#SSI|

|^ The |/.#ssi| directive allows multiple SSI directives to be used without the
requirement to enclose them in the normal HTML comment tags (i.e. ).
This helps reduce the clutter in an SSI document that uses the extended
capabilities of variable assignment and flow control. Document HTML cannot be
included between the opening and closing comment elements of the "#ssi" tag,
although of course document output can be generated using the "#echo" tag.

|code|

|!code|

|^ The example SSI document
|link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=ssi&text=plain|\
WASD_ROOT:[WASDOC.ENV]XSSI.SHTML| will
|link%|/wasd_root/wasdoc/env/xssi.shtml|demonstrate| this concept.

|3.#STOP|

|^ The |/.#stop| directive causes the server to stop processing the virtual
document.  It can be used with flow control structures to conditionally process
only part of a virtual document.  Note that the |/.#exit| directive also is
available, it stops processing of the current file (for nested #includes,
etc.). 

|code|

|!code|
 
|2Variables|

|^ The SSI processor maintains information about the server, date and time,
request path, request parameters, etc., accessible via |/variable name||.
Although these |/server variables| cannot be modified by the document the
processor also allows the author to create and assign new |/document variables|
by name.  SSI variables have global scope, with a small number of exceptions
listed below.  That is, the same set of variables are shared with the parent
document by any other SSI documents |/.#included||, and any included by those,
etc.

|^ Local variables:

|bullet#|
|item| DOCUMENT_DEPTH |-| the current nesting level for #included SSI files
|item| PARENT_FILE_NAME |-| if an #included SSI file the name of the including file
|item|THIS_FILE_NAME |-| the name of the SSI file currently being processed
|!bullet|

|^ One other special-purpose variable, THE_FILE_NAME, see |link|THE_FILE_NAME||.

|^ Server assigned variables comprise some SSI-specific as well as the same
CGI variables available to CGI scripts. These may be found listed in the
|link%|../scripting/##CGI Variables++in++WASD Scripting| document.

The following link provides a list of the |link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=ssi&printenv=yes|\ SSI and CGI variables| available to SSI documents. |^ Whenever a directive uses information from a tag (see |link|Directive Syntax||) values from variables may be substituted as as a whole or partial value. This is done using curly braces to delimit the variable name. For example |code| |!code| would include the file named by the contents of a variable named "FILENAME". When using a variable in a tag it is not necessary to enclose the tag parameter in quotation marks unless there is additional literal text. Variables may also be used within literal strings, producing a compound, resultant string, as in the following example |code| |!code| |^ Variables are considered numeric when they begin with a digit. Those beginning with an alphabetic are considered to have a numeric value of zero. |^ Variables are considered to be boolean |/false| if empty and |/true| when not empty. |0Substrings| |^ It is also possible to extract substrings from variables using the following syntax, |code| {|/variable-name||,|/start-index||,|/count||} |!code| |^ where the start-index begins with the zeroth character and numbers up to the last character in the string, and count may be zero or any positive number. If only one number is supplied it is regarded as a count and the string is extracted from the zeroth character. |^ To illustrate, |code| |!code| |^ would output |code| That was an example! |!code| |0Other "Functions"| |bullet| |item| |*LENGTH - || This "function" returns the length of the parameter string (or substring). |code| {|/variable-name||[,|/start-index||],|/count||]],length} |!code| |^ For example |code| |!code| |^ would output |code| "This is an example!" is 19 characters long. "is" is 2 characters long! |!code| |item| |*EXISTS |-| | This "function" returns |/true| if the variable exists and |/false| if it does not. This is useful as accessing a non-existant variable will result in an SSI error message with document processing ceasing! |code| var={|/variable-name||,exists} |!code| |^ For example |code| "BOGUS_VARIABLE" exists! "BOGUS_VARIABLE" does NOT exist! |!code| |!bullet| |^ The example SSI document |link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=ssi&text=plain|\ WASD_ROOT:[WASDOC.ENV]XSSI.SHTML| can |link%|/wasd_root/wasdoc/env/xssi.shtml|demonstrate| these concepts. |2Flow Control| |^ WASD SSI allows blocks of document to be conditionally processed. This uses constructs in a similar way to any programming language. The emphasis has been on simplicity and speed of processing. No complex expression parser is provided. Despite this, complex document constructs can be implemented. Flow control structures may be nested up to eight levels. |bullet| |item| |*.#if |-| | Marks the start of a conditionally processed block. If evaluated true the block is processed. |item| |*.#orif |-| | Allows a document block to be processed if one of multiple conditions are met. Must be used immediately following a "#if" or "elif". (This is the only really WASD-idiosyncratic element) |item| |*.#elif |-| | Allows a series of conditionals to be tested each with its own document block available for processing. Allows a type of case statement to be constructed. |item| |*.#else |-| | Provides a default document block following unsuccessful "#if", "orif" and "elif" testing and consequent non-processed blocks. |item| |*.#endif |-| | Terminates a conditional block. |!bullet| |^ The "#if", "#orif" and "#elif" directives must provide an evaluation. This can be single variable, which if numeric and non-zero is considered true, if zero if false, or can be a string, which if empty is false, and if not empty is true. Tests can be made against the variable which when evaluated return a true or false. Multiple tests may be made against the one variable, or against more than one variable. Multiple tests act as a logical AND of the results and terminate when the first fails. |bullet| |item| |*eqs |-| | If the supplied string is the same as the variable string. |item| |*srch |-| | If the variable string matches the supplied search string. The search string may contain the |=.*|| (asterisk), matching any zero or more characters, and |=.%| (percentage), matching any one character. |item| |*eq |-| | If the numeric value of the variable is the same as that of the supplied number. For a numeric value test to be legitimate both values must begin with a digit. Those beginning with an alphabetic are considered zero. |item| |*lt |-| | If the numeric value of the variable is less than that of the supplied number. |item| |*gt |-| | If the numeric value of the variable is greater than that of the supplied number. |!bullet| |^ Any evaluation can have the result negated by prefixing it with an exclamation point. For instance, the first of these examples would produce a |/false| result, the second |/true||. |code| |!code| |^ The following is a simple example illustration of variable setting, use of variable substrings, and conditional processing of document blocks. |code| <!--#echo var={GREETING} --> <!--#echo var="{REMOTE_HOST}!" -->

Simple XSSI Demonstration

, the time here is . (Sorry, I do not know your name, DNS lookup must be disabled!) |!code| |^ The example SSI document |link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=ssi&text=plain|\ WASD_ROOT:[WASDOC.ENV]XSSI.SHTML| further |link%|/wasd_root/wasdoc/env/xssi.shtml|illustrates| these concepts. |2Query Strings| |^ A query string may be passed to an SSI document in much the same way as to a CGI script. In this way the behaviour of the document can be varied in accordance to information explicitly passed to it when accessed. To prevent the server's default query engine being given the request precede any query string with "?httpd=ssi". The server detects this and passes the request instead to the SSI processor. Just append the desired query string components to this as if they were form elements. For example: |code| ?httpd=ssi&printenv=no ?httpd=ssi&printenv=yes ?httpd=ssi&trace=yes&test2=one&test2=two&test3=three |!code| |^ The following link uses the example SSI document |link%|/wasd_root/wasdoc/env/xssi.shtml?httpd=ssi&text=plain|\ WASD_ROOT:[WASDOC.ENV]XSSI.SHTML| to |link%|/wasd_root/wasdoc/env/xssi.shtml|demonstrate| this. Look for the (FORM_TEST1=one), etc. |2File and Virtual Specifications| |^ Documents may be specified using either the "FILE" or "VIRTUAL" tags. |^ The "FILE" tag expects an absolute VMS file specification. |^ The "VIRTUAL" tag expects an URL-style path to a document. This can be an absolute or relative path. See |link|Document Specification| for further details. |3THE_FILE_NAME| |^ Generally, when an error are encountered document processing halts and and an error report is generated. For some common circumstances, in particular the existance or not of a particular file, may require an alternative action. For file activities (e.g. #include, #flastmod, #created, #fsize) the optional fmt="" tag provides some measure of control on error behaviour. If the format string begins with a "?" files not found are not reported as errors and processing continues. Other file systems errors, such as directory not found, syntax errors, etc., are always reported. |^ Every time a file is accessed (e.g. #include, #flastmod) the server variable THE_FILE_NAME gets set to that name if successful, or reset to empty if unsuccessful. This variable can be checked to determine success or otherwise. |bullet| |item| For #included files, the 'fmt="?"' just suppresses an error report, if the file exists then it is included. |item| For #modified file specifications use 'fmt="?"' to suppress error reporting on evaluation of files that may exist but are not mandatory. |item| For file statistic directives (e.g. #flastmod, #fcreated, #fsize) the 'fmt="?"' tag completely suppresses all output as well as error reporting. This can be used to check for the existance of a file. For example if the file TEST.TXT exists in the following example the variable THE_FILE_NAME would contain the full file name, if it does not exist it would be empty, and the code example would behave accordingly. |code| File does not exist! File exists! |!code| |!bullet| |2Time Format| |^ Whenever a time directive is used an optional tag can be included to specify the format of the output. The default looks a little VMS-ish. If a format specification is made it must confirm to the C programming language function |/strftime()||. |^ The format specifier follows a similar syntax to the C standard library |/printf()| family of functions, where conversion specifiers are introduced by percentage symbols. Here are some example uses: |code| The date is . The time is . The day-of-the-week is . |!code| |^ A problem with any supplied time formatting specification will be reported. |^ The following table provides the general conversion specifiers. For further information on the formatting process refer to a C programming library document on the |/strftime()| function. |0strftime() Format Directives| |table| |~_ |: Specifier|: Replaced by |~ |~#* |. a |. The locale's abbreviated weekday name |~ |. A |. The locale's full weekday name |~ |. b |. The locale's abbreviated month name |~ |. B |. The locale's full month name |~ |. c |. The locale's appropriate date and time representation |~ |. C |. The century number (the year divided by 100 and truncated to an integer) as a decimal number (00 - 99) |~ |. d |. The day of the month as a decimal number (01 - 31) |~ |. D |. Same as %m/%d/%y |~ |. e |. The day of the month as a decimal number (1 - 31) in a 2 digit field with the leading space character fill |~ |. Ec |. The locale's alternative date and time representation |~ |. EC |. The name of the base year (period) in the locale's alternative representation |~ |. Ex |. The locale's alternative date representation |~ |. EX |. The locale's alternative time representation |~ |. Ey |. The offset from the base year (%EC) in the locale's alternative representation |~ |. EY |. The locale's full alternative year representation |~ |. h |. Same as %b |~ |. H |. The hour (24-hour clock) as a decimal number (00 - 23) |~ |. I |. The hour (12-hour clock) as a decimal number (01 - 12) |~ |. j |. The day of the year as a decimal number (001 - 366) |~ |. m |. The month as a decimal number (01 - 12) |~ |. M |. The minute as a decimal number (00 - 59) |~ |. n |. The newline character |~ |. Od |. The day of the month using the locale's alternative numeric symbols |~ |. Oe |. The date of the month using the locale's alternative numeric symbols |~ |. OH |. The hour (24-hour clock) using the locale's alternative numeric symbols |~ |. OI |. The hour (12-hour clock) using the locale's alternative numeric symbols |~ |. Om |. The month using the locale's alternative numeric symbols |~ |. OM |. The minutes using the locale's alternative numeric symbols |~ |. OS |. The seconds using the locale's alternative numeric symbols |~ |. Ou |. The weekday as a number in the locale's alternative representation (Monday=1) |~ |. OU |. The week number of the year (Sunday as the first day of the week) using the locale's alternative numeric symbols |~ |. OV |. The week number of the year (Monday as the first day of the week) as a decimal number (01 -53) using the locale's alternative numeric symbols. If the week containing January 1 has four or more days in the new year, it is considered as week 1. Otherwise, it is considered as week 53 of the previous year, and the next week is week 1. |~ |. Ow |. The weekday as a number (Sunday=0) using the locale's alternative numeric symbols |~ |. OW |. The week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols |~ |. Oy |. The year without the century using the locale's alternative numeric symbols |~ |. p |. The locale's equivalent of the AM/PM designations associated with a 12-hour clock |~ |. r |. The time in AM/PM notation |~ |. R |. The time in 24-hour notation (%H:%M) |~ |. S |. The second as a decimal number (00 - 61) |~ |. t |. The tab character |~ |. T |. The time (%H:%M:%S) |~ |. u |. The weekday as a decimal number between 1 and 7 (Monday=1) |~ |. U |. The week number of the year (the first Sunday as the first day of week 1) as a decimal number (00 - 53) |~ |. V |. The week number of the year (Monday as the first day of the week) as a decimal number (00 - 53). If the week containing January 1 has four or more days in the new year, it is considered as week 1. Otherwise, it is considered as week 53 of the previous year, and the next week is week 1. |~ |. w |. The weekday as a decimal number (0 [Sunday] - 6) |~ |. W |. The week number of the year (the first Monday as the first day of week 1) as a decimal number (00 - 53) |~ |. x |. The locale's appropriate date representation |~ |. X |. The locale's appropriate time representation |~ |. y |. The year without century as a decimal number (00 - 99) |~ |. Y |. The year with century as a decimal number |~ |. Z |. Timezone name or abbreviation. If timezone information is not available, no character is output. |~ |. % |. % |!table| |2OSU Compatibility| |^ Essential compatibility with OSU Server Side Includes directives is provided. This is intended to ease any transition to WASD, as existing SSI documents will not need to be changed unless any of the WASD capabilities are required. To provide transparent processing of OSU |=..HTMLX| files ensure the following WASD configuration is in place. |^ In HTTPD$CONFIG file: |code| [AddType] .HTMLX text/x-shtml - OSU SSI HTML |!code| |^ Note that the content description must contain the string "OSU" to activate some compliancy behaviours. |^ In HTTPD$MAP file: |code| redirect /*.*.htmlx /*.htmlx?httpd=ssi&__part=* |!code| |^ This provides a mechanism for the OSU part-document facility. (Yes, the "__part" has two leading underscores!) |0OSU Directives| |^ The following OSU directives are provided specifically for OSU compatibility, although there is no reason why most of these may not also be deployed in general WASD SSI documents if there is a requirement. Note that these are OSU-specifics, other OSU directives are provided by the standard WASD SSI engine. |9OSU Compatible Directives| |table| |~_ |: Directive|: Description |~ |~#* |. #begin |/label [|/label||]| |. delimit a part-document (see |link|OSU "Part"s||) |~ |. #config verify=1 |. enable commented-tag trace output |~ |. #echo accesses |. document access count |~ |. #echo accesses_ordinal |. document access count |~ |. #echo getenv="" |. output logical or symbol |~ |. #echo hw_name |. system hardware name |~ |. #echo server_name |. HTTPd server host name |~ |. #echo server_version |. HTTPd software version |~ |. #echo vms_version |. HTTPd system version of VMS |~ |. #end |/label| [|/label||] |. delimit a part-document (see |link|OSU "Part"s||) |~ |. #include [file\|virtual]="" part="|/label||" |. include only part of a virtual document |!table| |^ If WASD is configured for OSU SSI compatibility the following link provides an online demonstration as well as further explanation of the OSU SSI engine using an OSU preprocessor document from the distribution (included within copyright compliance). |^+ |link%=|/wasd_root/src/osu/preproc.htmlx| |^ How do we know WASD is processing it? Look for the |/.#echo var="GETENV=SYS$REM_ID"|| towards the end of the document. It should indicate |>>."[VARIABLE_DOES_NOT_EXIST!]"| because it's attempting to output a DECnet-related logical name! |0OSU "Part"s| |^ The OSU processor allows for delimited subsections of an |/.#include||d document, or a URL referenced document for that matter, to be included in the output. This is supported, but only for compatibility. It is only enabled for ".HTMLX" documents and if otherwise used may interact unexpectedly with WASD SSI flow-control. |2Script-Generated SSI Documents| |^ It is possible to have script output passed back through the SSI engine for markup. This approach might allow script output to automatically be wrapped in standard site headers and footers for example. Essentially the script must output an SSI-markup response body and include in the otherwise standard CGI response header a field containing "Script-Control: X-content-handler=SSI". The following example in DCL show the essential elements of such a script. |code| $ say = "write sys$output" $ say "Status: 200" $ say "Script-Control: X-content-handler=SSI"" $ say "" $ say "" $ say "" $ say "Example of X-content-handler=SSI" $ say "" $ say "" $ say "" $ say "

Example of X-content-handler:SSI

" $ say "Hi there " $ say "" $ say "" $ say "" |!code|