SREhttp/2 Manual|| SSIs|| SSIcache|| SSI_VARS

## SREhttp/2: Using Server Side Includes

### Contents:

- The REPLACE keyphrase
- The INCLUDE keyphrase
- The INTERPRET keyphrase
- The SELECT keyphrase
- The CACHE keyphrase
- Support for NCSA HTTPD server side include
- Processing of SSI keyphrases

One of the advantages of SREhttp/2 is the extensive support for a variety of server side includes. These server side includes (SSI's) let you easily create dynamic documents. In particular, inclusion of files, text strings, and transient variables (such as the time, date, and number of requests) are easy to accomplish, requiring modifications to your HTML documents, and not to the server software.

SREhttp/2 supports two sets of SSIs -- the NCSA set of SSIs, and a set of SREhttp/2-style SSIs. Both sets require the inclusion of special keyphrases in one's HTML documents. When an HTML document is requested, SREhttp/2 will detect these keyphrases, and perform textual substitutions.

### Indicating HTML files that contain SSIs

By default, SREhttp/2 will perform server side includes on all files that have either a `SHT` or a SHTML extension.

- To include other types of files, you can modify the SSI_EXTENSIONS parameter.
- Or, you can use the DO_SSI selector-specific permission.

### Specifying SREhttp/2 SSI Keyphrase

The basic structure of a SSI keyphrase is:
- <!-- KEYWORD `` argument `` -->
where:

- `<!--` and `-->` (the HTML comment delimiters) bracket the keyphrase.

- KEYWORD can be one of...
  - SELECT -- used to selectively include blocks of HTML code
  - REPLACE -- used to "replace strings"
  - INCLUDE -- used to "include files"
  - INTERPRET -- used to "include the results of a custom-designed REXX routine"
  - CACHE -- controls SREhttp/2's server side include CACHE
  - #cmd -- NCSA HTTPD style server side includes; such as: #INCLUDE #ECHO #IF #FLASTMOD and #EXEC.

- argument is a string containing "arguments" that are used, in conjunction with the keyphrase, to dictate how SREhttp/2 should modify this document.

Examples:
- `<-- REPLACE CREATION_DATE --> :`
- `<-- INCLUDE ADDLIST.HTM -- >`
- `<-- #FLASTMOD FILE="srehttp2.htm" -->`

#### Alternate keyphrases

In the interests of brevity, and to help avoid conflicts with other html comments that aren't comments , there are several modifications you can make to these KEYWORDS.

1. If desired, you can add a "preface" (such as the ! character) to the definitions of the first five keywords (i.e.; to use `!REPLACE` instead of `REPLACE`). For the details, see the user changeable parameters section of the SREH2INI.RXX file (in your SREHTTP2 directory).
2. You can use several shorthands:
   - `%` instead of `REPLACE` .
     For example, `<-- REPLACE CREATION_DATE -->` is the same as `<-- % CREATION_DATE -->`
   - `$` instead of `INTERPRET FILE`
   - `#` instead of `INTERPRET CODE`
   For further details, see the top of SREH2INI.RXX.

#### Miscellaneous Notes

- When SREhttp/2 finds a keyphrase, it will ALWAYS remove the keyphrase, and replace it with the file or string dictated by the KEYWORD argument . This replacement occurs at the position in the document that was occupied by the keyphrase. If a faulty keyphrase is encountered (i.e.; a non-supported argument is used), SREhttp/2 will remove it.
- The SELECT and #IF keyphrases are a little different: they dictate whether the "block of HTML code" that follows the SELECT (or #IF) keyphrase is to be retained. Thus, these are best thought of as a "server side excludes" -- the keyphrase is always removed, but sometimes so is a lot of other stuff!
- The CACHE keyphrase is used to control SREhttp/2's caching of documents that contain server side includes (it is not used to control the SRE2003 cache, or external proxy caches).
- As a more general type of "server side include"; you can use replacement-rules -- these perform textual replacements over your entire document; and may be specified generically or on a selector specific basis.
- You can specify a header and a footer to add to all SSI-enabled documents.

Back to top

### The REPLACE keyphrase

Syntax:
`<!-- REPLACE Varname -->`
where `Varname` is the name of a static or dynamic variable. Note that you can use % instead of REPLACE.

The REPLACE keyword is used to insert dynamically determined information and short (static) strings into a document. SREhttp/2 recognizes a number of "built-in" `Varnames`. SREhttp/2 will also recognize custom-defined (and possibly host-specific) `Varnames` defined in the SSI_VARS.CFG file(s).

The "built-in" `Varnames` are:

DATE and DATE_GMT | todays GMT date (i.e.; `28 May 2002 GMT` )
TIME and TIME_GMT | current time (GMT) (i.e.; `17:17:40 GMT` ; GMT is not added)
DATELOCAL | current date (local)
TIMELOCAL | current time (local)
DATETIME | current GMT date and time (i.e.; `Tue, 28 May 2002 17:17:40 GMT` )
DATETIME_LOCAL | current date and time (i.e.; `Tuesday, 13:17:41 28 May 2002` )
USERNAME | The client's user name, as provided by an Authorization: request header. If no authorization request header was sent, then this will be blank.
CLIENTNAME | the client's IP name (the name corresponding to his IP address)
FILTER_NAME | The name of the filter (i.e.; `SREhttp/2 ver 1.12d)`.
CREATION | Short message stating (local) creation time and date of the document
CREATION_DATE | Creation date of document
CREATION_TIME | Creation time of document
READ_HEAD or HEADER | Displays (using a <PRE>> format) the "request headers". This can be a handy debugging tool.
REFERER | The address of the server that refered the client to your site, as determined by a `Refefer:` request header (which is often unavailable).
BROWSER | : The name of the web browser the client is using (as provided by the `User-Agent` request header).
URL | The current URL (includes the servername and serverport)
SERVERNAME | The domain name of the server (i.e.; WWW.MYORG.NET). If multiple hosts, this will be the domain name of the server to whom the request was directed.
SERVER | the server software (i.e. SRE2003 ver 1.1 )
OPTION n | the "nth" option in the request selector. Options are found after `?` in the request selector; and they are seperated by &. For example, a request selector of `/foo/bar.sht?option1=abc&opt2=def` has two options: `option1=abc` and `opt2=def`.
HITS and HITS_FILE | A string stating the number of hits for the URL or the file (respectively) being requested. For example:`# of hits=51`
CACHE field | Display information the SSI-cache status of this document. `Field` can be empty, in which case summary information is returned. Otherwise, the value of the particular SSI-cache field is returned. For details on SSI-cache fields, see SSICACHE.HTM.

If none of the above matches argument , the custom variables specified in SSI_VARS.CFG are checked.

> You can include `argument placeholders` to this custom replacement; they will be replaced by `arguments` included in the REPLACE keyphrase -- see SSI_VARS.HTM for the details.

Examples | `<!-- REPLACE TIME --> <!-- % URL --> <!-- % ODOM MYDOC1 -->`

#### HITS and HITS_FILE -- more details Optional fields | you can include 3 (comma delimited) arguments after the `HITS` or `HITS_FILE`: alternative_id : instead of the URL or the file, you can lookup the number of hits for this alternative id. You can use any string as an alternative id (such as a filename). prefix: the prefix is written before the hit-count. If not specified, a default prefix (`# of hits=`) is used. postfix: the postfix is written after the hit-count. If not specified, no postfix is added. Example: `<-- Replace hits TigerDocs , You are visitor , to the Tiger Archives -->`
Notes: | If you've specified a non-zero value for the !HIT_DURATION parameter, then SREhttp/2 will check to see if this client has recently requested this resource. If he as, then the count will not be augmented. If you want just the number of hits, without any prefix or postfix, you can use `COUNT` or `COUNT_FILES` instead of `HITS` and `HITS_FILE`. Hit information is stored in the `HITS.CNT` file in SREHTTP2\WORKDATA. `HITS.CNT` is a special, text-like SRE2003 data series file. You can view it with any text viewer or editor, but you should not try to edit it. We recommend using the data series viewer Note that a given document may be reached via several different selectors (say, due to several aliases pointing to the same file), each of which will have a seperate counter. In such a case, each `HITS` will have a unique count. In contrast, if HITS_FILE is used, a cumulative count is kept, with the cumulation across all requests for this file (regardless of the selector that was used to specify this file). Alternatively, you can use specify an `alternative_id` (as mentioned above).

Back to top

### The INCLUDE keyphrase

Syntax: `<!-- INCLUDE FileName -->` , where FileName is the name of the File to be included.

The INCLUDE keyphrase instructs SREhttp/2 to include the contents of a file into the requested document (where argument is the file-to-be-included). For example, `INCLUDE PHONE.LST` would cause the contents of the file `PHONE.LST` (in your data directory) to be inserted into the document.

##### Examples

<!-- include buttons.bar -->
<!-- include newtoday.txt -->

Notes | It is recommended that INCLUDE keyphrases appear on seperate lines of a file (with no other HTML statements or text). The file is treated as a long string (that contains linefeeds) and replaces the keyphrase -- anything before or after the keyphrase (on the same line) will be placed just before and after the contents of the file. FileName is interpreted relative to the Data Directory, or to a "local" virtual directory . The INCLUDE keyphrase will check for potentially fatal, recursive file INCLUDES, and disallow them. Since this check is very primitive, it will also disallow multiple INCLUDEs of the same file. If you need to include a file multiple times (say, to position a button bar at the top and bottom of your document), you can use the #INCLUDE keyphrase. INCLUDE, in combination with the INTERPRET keyphrase, facilitates customization of your documents , based on client specific informaton (such as the `user agent` )!

Back to top

### The INTERPRET keyphrase

Syntax:
`<!-- INTERPRET FILE xxx.RXX -->`
or...
`<!-- INTERPRET CODE rexx statement ; .. -->`

INTERPRET provides a means of including and executing REXX code. There are two ways of specifying this `INTERPRET block` -- by including it directly in the SSI keyphrase, or by specifying a file.

1. `INTERPRET CODE statment 1 ; statement 2 ; ...` ;
   where:
   each `statement n` is a valid REXX statements (and each statement is seperated by a semi-colon). For example:
   `tmp1=server() ; return tmp1`

2. `INTERPRET FILE Filename arg_list`
   where:
3. `Filename` is a file containing REXX code (`filename` is assumed to be relative to the SREhttp/2 addon directory, or to a "local" virtual directory).
4. `arg_list` is an optional comma delimited list of "arguments"

Alternate syntax: | You can use `#` instead of `INTERPRET CODE` You can use `$` instead of `INTERPRET FILE`
Example | If your document contains the keyphrase: <!-- INTERPRET FILE GOBED.RXX--> (`or, equivalently, <!-- $ GOBED.RXX-->` ) and GOBED.RXX contains: `tmp1=time('h') ; if tmp1<6 | tmp1>23 then return " <em> It is late, GO TO BED! </em> ";` then the phrase It is late, `GO TO BED!` will appear in your document whenever the local time (on the server) is between 11:00 P.M and 6 A.M.

There are two ways for an `INTERPRET` block to return a string to include in the html document:

1. A QUEUE (or PUSH) command -- with each QUEUEd (or PUSHed) string displayed in the appropriate order
2. `RETURN 'stuff to include'`

- Notes | When processing an `INTERPRET block`, syntax checking is turned on -- coding errors will cause the code-block to fail, but will not crash SRE2003. Instead, the INTERPRET keyphrase will be ignored. `INTERPRET FILE` blocks are "interpreted" by SREhttp/2 -- they are not called as external procedures. Therefore: an INTERPRET FILE code-block can not contain procedures or subroutines, and can not contain `signal name` statements or `labels:` This inconvenience can be partially ameliorated by calling "external" procedures from within the INTERPRET FILE code block. The comma delimited `arg_list` can be accessed within the `INTERPRET code block` by using the usual REXX syntax; i.e. `parse arg aval1,aval2`. You can include up to 6 arguments. The `ARG_LIST` is also stored in the `INTERP_ARGS.` array, with `INTERP_ARGS.0` the number of arguments (not limited to 6) The following variables can be accessed by a INTERPRETed code: `servername` : IP name of the server (useful on multi-host servers) `host_nickname` : SREhttp/2's host nickname (for this `servername`) `selector` : The request selector (after removal of !modifiers, internal redirection, etc.) `request_line` : The original request line. For example: `GET /docs/hello.shtml HTTP/1.0` `usedfile`: The file (that contains this INTERPRET) `privset` : A list of the client's privileges (not including secret privileges). `verbose` : The VERBOSE variable (higher values for more PMPRINTF output) `id_info` : Identifier info that can be used in several SRE2003 functions `datadir`: The "default data directory" (may be host specific) `usedfile` : The fully qualified name of the requested file `interpret_element` : The full text of this INTERPRET (either what follows `INTERPRET CODE`, or the contents of the `INTERPRET FILE` file) SREH2_HTML_COMMENT function. SREH2_HTML_COMMENT will wrap a string with <!-- and -->, thereby avoiding confusion when using INTERPRET CODE (since SREhttp/2 uses the first --> it finds as an `end of keyphrase` delimiter).
  For example: |
      <!-- INTERPRET CODE
              if time('S')>43200  then ;
                return sreh2_html_comment('INCLUDE TABLEPM.HTM') ;
              else ;
                return sreh2_html_comment('INCLUDE TABLEAM.HTM ');
      -->
- Note that you can include html comments in INTERPRET FILE. Thus, sreh2_html_comment is only needed when using INTERPRET CODE. You can use the SRE_MOVE_RESPONSE function to redirect. For example:
      <!-- INTERPRET CODE
       if sre_extract('clients')>3 then do ;
          foo=sre_move_response(301,'http://foo.bar.net/busysite.txt') ;
       end;
       else do ;
          foo=sre_move_response(301,'pages1/oksite.html',302);
       end;
       return foo;
      -->
Note that the first argument is the type of redirect. It can be: 301 (permanent redirection), 302 (temporary redirection), and 200 (text message redirect). Also, relative URIs (selectors) are interpreted relative to your server (and port). You can use the various SRE2003 functions, and the SREhttp/2 procedures, If you have multiple `INTERPRETs` in a document, you can use the GLOBALS. stem variable to retain variables. All other variables are local to each `INTERPRET` keyphrase. For example, you could set GLOBALS.!TIME=time() in an early `INTERPRET` , and reference GLOBALS.!TIME later in the document (say, to compute the time it takes to process some intermediate steps). The querylist options (the stuff following a `?`) are stored in the `OPTION.` stem variable; with OPTION.0 the number of options. Example: given a request of `/foo.sht?trucks&canaries` then ...`option.0=2 option.1=trucks option.2=canaries` `INTERPRET` will be ignored if a `INTERPRET` SSI suppression option is specified When using `INTERPRET CODE` : each statement must end with a semi-colon. However, lines in an INTERPRET FILE do not have to end with a semi-colon. If your needs are complicated, you might want to write your own SREhttp/2 addon; typically this would be a REXX routine that would generate an HTML document that SREhttp/2 would then return to the client However, when combined with the other keyphrases, the INTERPRET keyphrase can accomplish quite a bit of customization! `INTERP.REX, DIRINFO.REX, DYNPRIV.REX`, and `SHOWFILE.REX` are examples of `INTERPRET FILE` files. They are installed in your SREHTTP2\ADDON directory.

Back to top

### The SELECT keyphrase

The SELECT, and the #IF, keyphrases are qualitatively different from the other keyphrases -- they act as a "conditional server side include" of HTML code that is already in your document. The power of SELECT is the ability to check dynamic variables (such as the client's IP address, or his user agent), and retain or exclude a portion of the HTML document accordingly.

A SELECT keyphrase expects an argument containing a block of REXX code, just like the code blocks used in the INTERPRET keyphrase. This block of code will be `interpreted`. The code block should "exit" with either a `RETURN 1` or `RETURN 0` , where:

- `RETURN 1` : the subsequent HTML text block is retained
- `RETURN 0` :the subsequent HTML text block is deleted. The "subsequent HTML text block" is delimited by a `SELECT END` keyphrase, and can be of any length (if no `SELECT END` keyphrase is encountered, the remainder of the file is dropped). Lastly, if there is no RETURN, the code block is retained (i.e.; the default is RETURN 1).

  Example:

         <!--SELECT
            tmp.1=sre_extract('clientaddr') ;
            tmp.2=sreh2_value('SUPERUSERS');
            tmp.3=wordpos(tmp.1,tmp.2); ;
            if tmp.3=0 then return 0
         -->
               <em> Hello!  You have SuperUser Privileges !! </em>
         <!-- SELECT END -->

  Note that `RETURN 1` is assumed by default, hence when the clients IP address is listed in the an OWNER variable (and the code block ends without a return) the `Hello! ...` message will not be deleted.

  Notes | SELECT code blocks can access the same variables as INTERPRET blocks SELECT will not be done if either an `INTERPRET` or a `SELECT` SSI suppression option is specified SELECT blocks can not be nested. They may contain other keyphrases. The XSSI #IF ssi element can also be used for conditional includes. #IF can be nested, but the test conditions (string comparisons) are simpler.

  Back to top

  ### The CACHE keyphrase

  To improve performance, SREhttp/2 will "cache" HTML documents that have server side includes (SSI). This caching is of the document after the SSIs have been performed. In simple cases SREhttp/2 can send this cached file, without having to repeat the actual process of SSI lookups, etc. Needless to say, this can greatly improve server performance.

  For a complete description of SREhttp/2's SSI-caching algorithim, and of the various options available for the CACHE keyphrase, please read SSICACHE.HTM . What follows is a very brief description of the options available for the CACHE keyphrase.

  <!-- cache no -->
    Do not cache this document
  <!-- cache asis -->
    Use a cached version "as is"
  <!-- cache notrigger -->
    Do not check the trigger files; but do check the own file.
  <!-- cache duration nnn -->
    Set the lifespan for this file's cache entry, where nnn is the number of (possibly fractional) days.
  <!-- cache trigger file1 file2 .. -->
    Check the file-stamps of these fully qualified files.
  <!-- cache trigger_type stamp -->
    Selects which field(s) of the trigger file-stamps to check.

  Back to top

  ### Support for NCSA HTTPD server side include

  With only minor exceptions, the server side include syntax of the NCSA HTTPD server is fully supported by SREhttp/2. These are invoked with a keyphrase of:

  > `<!-- #cmd option="value" -->`

  Where `cmd` can be: CONFIG ECHO EXEC FLASTMOD FSIZE IF INCLUDE SET

  #### Details on NCSA HTTPD server side includes

  - #INCLUDE: Include a file.
    `option` can be VIRTUAL or FILE. If VIRTUAL then value should be a relative file name (relative to the data directory or to a "local" virtual directory). If FILE, then value is interpreted relative to the directory containing the "requested file" (the file that contains this server side include).

    > Note: #INCLUDEd files will not be checked for recursive includes. To check for recursive includes, use the <!-- INCLUDE filename --> keyphrase.

    Examples: | `<!-- #include virtual="/samples/intro.doc" -->` If your data directory is `D:\WWW`, then `D:\WWW\SAMPLES\INTRO.DOC` will be included. `<!-- #include file="intro.doc" -->` If your data directory is `D:\WWW`, and if the selector containing this SSI is `/SAMP2/INDEX.HTM`, then `D:\WWW\SAMP2\INTRO.DOC` will be included. `<!-- #include file="/samples/intro.doc" -->` If your data directory is `D:\WWW`, and if the selector containing this SSI is `/SAMP2/INDEX.HTM`, then `D:\WWW\SAMP2\SAMPLES\INTRO.DOC` will be included.

  - #CONFIG: Configure some options.
    `option` can be:
    - ERRMSG: Error message to display when a bad request is made
    - SIZEFMT : If `value=ABBREV`, will display kilobytes or megabytes (as appropriate). Otherwise, displays exact byte count (with commas added).
    - SREhttp/2 modification: ABBREV will generate `nnn.nnM` style abbreviations (i.e.; `3.12M`); the standard seems to be `nnnM` (i.e.; `3M`). If you prefer this terser standard, use MABBREV instead of ABBREV.
    - TIMEFMT: A set of instructions on how to display time and date. These are based on the strftime C function -- see TIMEFMT.TXT for a description of the various options.

    Examples |
              <!-- #config sizefmt="abbrev" -->
              <!-- #config timefmt="%A , %c  (%r) ==is %j day of year" -->
              <!-- #config errmsg=" Sample error message " -->

  - #FLASTMOD: Modification date of a file.
    The `option` and `value` are the same as for #INCLUDE

    Examples |
              <!-- #flastmod virtual="/samples/intro.doc" -->
              <!-- #flastmod file="intro.doc" -->

  - #FSIZE: Size of a file
    The `option` and `value` are the same as for #INCLUDE

    Examples |
              <!-- #fsize virtual="/samples/intro.doc" -->
              <!-- #fsize file="intro.doc" -->

  - #EXEC: Execute a CGI script.
    `option` should equal CMD, and `value` should be a file name (in the CGI_BIN_DIR directory) of a CGI script (typically a REXX program or an executable). Note that the EXEC server side include captures the output of the script, and includes this output in the requested document. EXEC will not be done if NO_PROCESSING=YES, or if a NO_SSP permission applies to this selector.

    Example:

            <!-- #exec CMD=jcount?index.htm -->

  - #ECHO: Value of a variable
    `option` should be VAR, `value` should be a variable name. This is equivalent to the REPLACE keyphrase, but with different variable names (although many of them overlap).

    The supported variables are:

    > DOCUMENT_NAME, DOCUMENT_URI, DATE_LOCAL, DATE_GMT, LAST_MODIFIED, SERVER_SOFTWARE, SERVER_NAME, GATEWAY_INTERFACE, SERVER_PROTOCOL, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME, QUERY_STRING, REMOTE_HOST, REMOTE_ADDR, AUTH_TYPE, AUTH_NAME, HTTP_ACCEPT, HTTP_REFERER, HTTP_USER-AGENT

    Unsupported variables are (they really aren't relevant to server side includes):

    > PATH_INFO, PATH_TRANSLATED, REMOTE_IDENT, CONTENT_TYPE, CONTENT_LENGTH

    Examples |
           Server Software: <!-- #echo var="SERVER_SOFTWARE" -->
           GMT date and time: <!-- #echo var=DATE_GMT" -->
           Http accept: <!-- #echo var="HTTP_ACCEPT" -->
           Http user_agent: <!-- #echo var="HTTP_USER-AGENT" -->

  - #IF: Conditional inclusion of HTML
    The #IF element has the following syntax:

            <!--#if expr="test_condition" -->
                some html
            <!--#elif expr="test_condition" -->
                some other html
            <!--#else -->
                some default html
            <!--#endif -->

    The `if` element works like an if statement in a programming language. The test condition is evaluated and if the result is true, then the text until the next `elif`, `else`. or `endif` element is included in the output stream.

    The `elif` or `else` statements are used if the original test_condition is false. These elements are optional. Note that the first true statement is used, and `else` is always true (it does NOT take an `expr`).

    EXAMPLE: the below example will print "in foo" if the DOCUMENT_URI is /foo/file.html, "in bar" if it is /bar/file.html and "in neither" otherwise:

            <!--#if expr="\"$DOCUMENT_URI\" = \"/foo/file.html\"" -->
            in foo
            <!--#elif expr="\"$DOCUMENT_URI\" = \"/bar/file.html\"" -->
            in bar
            <!--#else -->
            in neither
            <!--#endif -->

    Notes:
    - #IF ... #ELIF ... #ELSE ... #ENDIF blocks can be nested.
    - The SREhttp/2 SELECT ssi element can also be used for conditional includes. SELECT can not be nested, but the test conditions can be far more elaborate (given that you understand REXX).
  - #SET: Define a variable
    The #SET element has the following syntax:
    `<!-- #set var="varname" value="a value" -->`
    These variables can be used (as a textual substitution) in any HTTPD-style server side include -- just prepend a $ before the varname. For example:

    > `<!-- #set var="foobar" value="hello world" -->
    > <!-- #echo var="$foobar" -->`

  Need more information on NCSA HTTPD server side includes (and the XSSI extensions)

  Back to top

  ### Processing of SSI keyphrases

  Server-side includes are processed in the following iterative order:
  1. The requested document is read into memory.
  2. Replacement-rules (if any are specified) are applied
  3. Headers and Footers, if specified, are included (they too are subject to replacement rules)
  4. The document, (that now includes headers and footers), is scanned for SSI keyphrases.
  5. Each SSI keyphrase is processed in order of appearance. Thus, actions of earlier keyphrases (such as setting of variables) may effect the processing of later SSI keyphrases.
  6. After all SSI keyphrases have been processed, the document is reassembled (the results of processing the SSI keyphrases are reinserted in to the text).
  7. The document is rescanned for new SSI-keyphrases (that may have been INCLUDED or otherwise generated by the first round of SSI-keyphrase processing). If any are found, go back to step 4
  8. This process continues until there are no more keyphrases.