WASD Hypertext Services - Technical Overview

[next] [previous] [contents] [full-page]

15 - Scripting: CGI

The information in this chapter merely outlines the WASD implementation details, which are in general very much vanilla CGI and WWW CGI (Common Gateway Interface) compliant, based the INTERNET-DRAFT authored by D.Robinson (drtr@ast.cam.ac.uk), 8 January 1996.


CGI Compliant Variables

Environment variables are provided to the script via DCL global symbols. Each CGI variable symbol name is prefixed with "WWW_" (by default, although this can be changed using the "/CGI_PREFIX" qualifier, see 5.3 - HTTPd Command Line, this is not recommended if the WASD VMS scripts are to be used, as they expect CGI variable symbols to be prefixed in this manner).


Extensions to CGI Variables

In line with other CGI implemenations, additional, non-compliant variables are provided to ease CGI interfacing. These provide the various components of the query string. A keyword query string and a form query string are parsed into separated variables, named

  WWW_KEY_number
  WWW_KEY_COUNT
  WWW_FORM_form-element-name

plus a number of non-"standard" CGI variables to assist in tailoring scripts for the WASD environment. Do not make your scripts dependent on any of these if portability is a goal. See the table below.


CGI Variable Capacity

DCL symbol values are limited to approximately 1024 characters. The CGI interface will provide symbols with values up to that limit if required. This should be sufficient for most circumstances.


CGI Variable Descriptions

Remember, all variables are prefixed by "WWW_".


NameDescription"Standard" CGI
AUTH_ACCESS"READ" or "READ+WRITE" (or empty)no
AUTH_GROUPauthentication group (or empty)no
AUTH_PASSWORDplain-text password, only if EXTERNAL realm (or empty)no
AUTH_REALMauthentication realm (or empty)no
AUTH_REALM_DESCRIPTIONbrowser displayed string (or empty)no
AUTH_TYPEauthentication type (BASIC or DIGEST)yes
CONTENT_LENGTH"Content-Length:" from request headeryes
CONTENT_TYPE"Content-Type:" from request headeryes
FORM_fieldquery string "&" separated form elementsno
GATEWAY_INTERFACE"CGI/1.1"yes
HTTP_ACCEPTany list of browser-accepted content typesoptional
HTTP_ACCEPT_CHARSETany list of browser-accepted character setsoptional
HTTP_ACCEPT_LANGUAGEany list of browser-accepted languagesoptional
HTTP_AUTHORIZATIONany from request headeroptional
HTTP_COOKIEany cookie sent by the clientoptional
HTTP_FORWARDEDany proxy/gateway hosts that forwarded the requestoptional
HTTP_HOSThost and port request was sent tooptional
HTTP_IF_MODIFIED_SINCEany last modified GMT time stringoptional
HTTP_PRAGMAany pragma directive of request headeroptional
HTTP_REFERERany source document URL for this requestoptional
HTTP_USER_AGENTclient/browser identification stringoptional
KEY_nquery string "+" separated elementsno
KEY_COUNTnumber of "+" separated elementsno
PATH_INFOvirtual path of data requested in URLyes
PATH_TRANSLATEDVMS file path of data requested in URLyes
QUERY_STRINGun-URL-decoded string following "?" in URLyes
REMOTE_ADDRIP host address of HTTP clientyes
REMOTE_HOSTIP host name of HTTP clientyes
REMOTE_USERauthenticated remote user name (or empty)yes
REQUEST_CHARSETany server-determined request character setno
REQUEST_METHOD"GET", "PUT", etc.yes
REQUEST_SCHEME"http:" or "https:"no
REQUEST_TIME_GMTGMT time request receivedno
REQUEST_TIME_LOCALLocal time request receivedno
SCRIPT_NAMEname of script being executed (e.g. "/query")yes
SECURITY_STATUSsecure request? ("NONE" or "SSL")no
SERVER_ADDRIP host name of server systemno
SERVER_CHARSETserver default character setno
SERVER_GMToffset from GMT (e.g. "+09:30")no
SERVER_NAMEIP host name of serveryes
SERVER_PROTOCOLHTTP protocol version (always "HTTP/1.0")yes
SERVER_PORTIP port request was received onyes
SERVER_SOFTWAREsoftware ID of HTTP serveryes
SSL_CIPHERcipher used for encryption (e.g. "RC4-MD5")no
SSL_CIPHER_KEYSIZEsize of cipher key (export:40, domestic:128)no
SSL_CLIENT_DNclient certificate distinguished nameno
SSL_CLIENT_CAclient certifying authorityno
SSL_SERVER_DNserver certificate distinguished nameno
SSL_SERVER_CAserver certifying authorityno
SSL_VERSIONprotocol version (e.g. "SSLv2")no



CGI Variable Demonstration

The basic CGI symbol names are demonstrated here with a call to a script that simply executes the following DCL code:

  $ SHOW SYMBOL WWW_*
  $ SHOW SYMBOL *
Note how the request components are represented for "ISINDEX"-style searching (third item) and a forms-based query (fourth item).
  1. <A HREF="/cgi-bin/cgi_symbols">
  2. <A HREF="/cgi-bin/cgi_symbols/ht_root/doc/htd">
  3. <A HREF="/cgi-bin/cgi_symbols/ht_root/doc/htd/*.*?string1+string2">
  4. <A HREF="/cgi-bin/cgi_symbols/ht_root/doc/htd?FirstField=for&SecondField=this">


15.1 - CGI Compliant Output

Script output must behave in a CGI-compliant fashion (by way of contrast, see 15.2 - Raw HTTP Output). That is, a CGI script may redirect the location of the document, using a Location: header line, or may supply a data stream beginning with a Content-Type: or Status: header line.

If the script output begins with a CGI-compliant "Content-Type: text/..." (text document) the HTTPd assumes that output will be line-oriented and requiring HTTP carriage-control (each record/line terminated by a line-feed), and will thereafter ensure each record it receives is correctly terminated before passing it to the client. In this way DCL procedure output (and the VMS CLI in general) is supported transparently. Any other content-type is assumed to be binary and no carriage control is enforced.


Example DCL Scripts

A simple script to provide the system time might be:

  $ say = "write sys$output"
  $! the next two lines make it CGI-compliant
  $ say "Content-Type: text/plain"
  $ say ""
  $! start of plain-text script output
  $ show time

A script to provide the system time more elaborately (using HTML):

  $ say = "write sys$output"
  $! the next two lines make it CGI-compliant
  $ say "Content-Type: text/html"
  $ say ""
  $! start of HTML script output
  $ say "<HTML>"
  $ say "Hello ''WWW_REMOTE_HOST'"  !(CGI variable)
  $ say "<P>"
  $ say "System time on node ''f$getsyi("nodename")' is:"
  $ say "<H1>''f$cvtime()'</H1>"
  $ say "</HTML>"


15.2 - Raw HTTP Output

A script does not have to output a CGI-compliant data stream. If it begins with a HTTP header status line (e.g. "HTTP/1.0 200 Success"), HTTPd assumes it will supply a raw HTTP data stream, containing all the HTTP requirements. This is the equivalent of the no-parse-header, or "nph..." named scripts of some environments.

Any such script must observe the HyperText Transfer Protocol, supplying a full header and body with correct carriage-control.


Raw HTTP DCL Script

The following example show a DCL script. Note the full HTTP header and each line explicitly terminated with a carriage-return and line-feed pair.

  $ lf[0,8] = %x0a
  $ say = "write sys$output"
  $! the next line determines that it is raw HTTP stream
  $ say "HTTP/1.0 200 Success" + lf
  $ say "Content-Type: text/html" + lf
  $! response header separating blank line
  $ say lf
  $! start of HTML script output
  $ say "<HTML>"
  $ say "Hello ''WWW_REMOTE_HOST'"
  $ say "<P>"
  $ say "Local time is ''WWW_REQUEST_TIME_LOCAL'"
  $ say "</HTML>"


CGIUTL Utility

To assist with the generation of HTTP responses, including the transfer of binary content from files (copying a file back to the client as part of the request), and the processing of the contents of POSTed requests from DCL the HT_ROOT:[SRC.MISC]CGIUTL.C is available. Also see DCL Processing of POSTed Content in this chapter.


Raw HTTP C Script

When scripting using the C programming language there can be considerable efficiencies to be gained by providing a binary output stream from the script. This may be simply provided using a code construct similar to following to reopen <stdout> in binary mode.

  /* reopen output stream so that the '\r' and '\n' are not filtered */
  #ifdef __DECC
     if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL)
        exit (vaxc$errno);
  #endif

This is used consistently in WASD scripts. Carriage control must be supplied as part of the C standard output (no differently to any other C program). Output can be be explicitly fflush()ed at any stage to overtly send output buffered by the C RTL to the client. If the fwrite() library function is used then to maintain the buffering efficiency an additional reopen() parameter is required following the "ctx=bin", "ctx=xplct".

The full HTTP header can be supplied (as in the following example) or just a CGI-compliant header output.

     fprintf (stdout,
  "HTTP/1.0 200 Success\r\n\
  Content-Type: text/html\r\n\
  \r\n\
  <HTML>\n\
  Hello %s\n\
  <P>\n\
  System time is %s\n\
  </HTML>\n",
     getenv("WWW_REMOTE_HOST"),
     getenv("WWW_REQUEST_TIME_LOCAL"));


15.3 - Raw HTTP Input (POST Processing)

For POST and PUT HTTP methods (e.g. a POSTed HTML form) the body of the request may be read from the HTTP$INPUT stream. For executable image scripts requiring the body to be present on SYS$INPUT (the C language <stdin> stream) a user-mode logical may be defined immediately before invoking the image, as in the example.

  $ EGSCRIPT = "$HT_EXE:EGSCRIPT.EXE"
  $ DEFINE /USER SYS$INPUT HTTP$INPUT
  $ EGSCRIPT

The HTTP$INPUT stream may be explicitly opened and read. Note that this is a raw stream, and HTTP lines (carriage-return/line-feed terminated sequences of characters) may have be blocked together for network transport. These would need to be explicity parsed by the program.

NOTE: Versions of the server prior to 4.3 supplied the full request (header then body) to the script. This was not fully CGI-compliant. Versions 4.3 and following supply only the body, although the previous behaviour may be explicitly selected using the configuration parameter [DclFullRequest].


DCL Processing of POSTed Content

To assist with the processing of the contents of POSTed requests from DCL the HT_ROOT:[SRC.MISC]CGIUTL.C is available. This utility reads the request body, decoding form-URL-encoded contents into DCL symbols and/or a scratch file, allowing a DCL procedure to easily and effectively process this form of request. An example form, HT_ROOT:[SRC.MISC]CGIUTL_EXAMPLE.HTML, and example script, HT_ROOT:[SCRIPT]CGIUTL_EXAMPLE.COM, shows how this utility may be deployed. This utility also has functionality for generating HTTP responses.


15.4 - CGI Function Library

A source code collection of C language functions useful for processing the more vexing aspects of CGI programming is available in

HT_ROOT:[SRC.MISC]CGILIB.C

Functionality includes

The WASD scripts use this library extensively and may serve as example applications.


[next] [previous] [contents] [full-page]