The current prototype server is implemented via a ``CGI-script'' [McC93] running under a normal NCSA httpd server [McC94]. Today, only the GET method is implemented. Since we envisage to extend the set of supported methods, we are writing our own HTTP [BL93] server. In figure 6 we have shown the processes after the creation of the CGI process following the GET request.
Figure 6: WWW Front End Architecture.
The HTML is generated from actions specified in the FORMATX part of the GPD for each item, terminal or non-terminal (as defined in the STRUCTURE part). The actions are written in a small application language using the parser included in the CIM layer.
The CGI program cgi2lincks takes one parameter - a path to a key file. The key file contains the host where LINCKS client w3lincks is running, the port number to connect to, current LINCKS user name for this incarnation of w3lincks, and a random key generated by w3lincks. This setup was inspired partly by the SQL gateway [Ng93].
After extracting the URL and the ``virtual'' path from the environment (per the CGI specification [McC93]), cgi2lincks connects to w3lincks, sends one line containing the key and the URL, and waits for the response. The CGI program copies any information sent by w3lincks to standard output. If there was no output generated by w3lincks, a warning message is sent.
The LINCKS database client w3lincks is similar to the X11 client xlincks. We removed all X11 related code and added a new general purpose module for generating HTML (or any text).
When starting w3lincks, it connects to a LINCKS database and login as a normal user. It writes the key file file, and waits for a connection from cgi2lincks. Notice that the w3lincks can only process one request at a time. When receiving a connection from the cgi2lincks, w3lincks verifies that the supplied key matches its own key. Moreover, we can restrict w3lincks to only accept connections from a specific host. After the verification step, we extract the view (GPD) from the URL as well as the path to a root object. The current syntax of the URL is:
URL ::= /<segment>/ ... /<segment>-<gpd> <segment> ::= <name> | <name>:<position> <name> ::= <shortname> | <group> : <field> <gpd>, <group, <field>, <shortname> ::= <id>
The ``shortname'' case is an internal mapping from a pair to a unique letter combination. This was initially implemented to keep the generated URL short (cf. `TP' with `Text:Paragraph'). The group:field is a name of an attribute or a link. The position parameter is only valid for links, and it enumerates the different object that the group:field points to. The position parameter defaults to zero (0), i.e the first link.
The starting point for the search is the `home page' of the login user (of w3lincks). Users can specify a special `home page' if they would like to avoid exporting their normal home page. Starting from the `home page', we traverse the path, following the links to the next object, looking up any ``shortname''. At the end of the path, we should have a root object and a view (GPD). To create a reference structure tree (section 3), we apply the GPD to the root object. Then, we do an infix traversal of the reference structure to generate output. For each of the nodes of the reference structure tree, we execute the statements in FORMATX part. Whenever the conditions in the FORMATX part is true, we execute the corresponding action which could result in the output of HTML or the extraction of images/sounds from the database.
The small language in the FORMATX part has a very simple syntax (lisp reminiscent) and basicly consists of expressions and function applications.
<FORMATX> ::= <formatxs> <formatxs>::= <formatx> | <formatxs> , <formatx> <formatx> ::= <function> ( <formatxs> ) -- function <string> ( <formatxs> ) -- FORMAT( .... ) <string> | <integer> | <identifier> | <var> | <attr>
When traversing the reference structure in infix order, the attributes below are used to restrict when and where the actions (e.g. mostly FORMAT(...)) are executed. The attributes are restrictions on the current position in the reference structure (tree). Notice that the two last attributes are special cases since they causes side effects. The ONCE attribute is used for executing an action only once and sets a flag in the reference structure. The NOREMAP attribute avoids re-mapping of the input characters (e.g. `<' to `&;' for HTML) in the leaf items.
AFTER/BEFORE -- before and after treating children FIRST/NOTFIRST -- first/not first for sibling nodes LAST/NOTLAST -- last/not last for sibling nodes LEAF/ROOT/NODE -- is it a leaf, root, or an internal node? PLACEHOLDER -- is it a place holder (i.e. no data in database)? ONCE -- action is executed only once NOREMAP -- disable remapping (to HTML, depends on EXPORT setting)
For the actions we have the following set of functions which have been sufficient so far:
CASE(integer-expr, 0-formatx, 1-formatx, ...) IF(integer-expr, formatx, formatx) -- true if non-zero EQ/GE/GT/LE/LT/NE(integer-expr,integer-expr) ATTR(grp0,fld0[,pos],grp1,fld1, ...) -- get an attribute value LINK(grp0,fld0[,pos],grp1,fld1, ...) -- get an binary image value I2STR(image) -- binary image to string N2STR(integer) -- number to string UNESCAPE/ESCAPE(string) -- for handling URLs FORMAT([printf-string] [,attribute]* [,string-expr]*) MACRO(name) -- execute macro `name' EXPORT(name) -- calls ROOTBEFORE and ROOTAFTER
Notice that the EXPORT function is only executed for the root node of the reference structure. The purpose is to specify: the output mode and thus character set mapping, default macros, default short name, as well as to execute prolog and epilog actions. The FORMAT corresponds to the `C' library function printf, but we are only using "%s". It is used to output the strings in leaf items in the reference structure.
We have the following set of variables for retrieving information, which can be used in any expression:
%GPDEXP% -- expansion GPD (view to use) %GPD% -- name of current GPD (used in current view) %ROOT% -- path from user root object to root object for this view %RPATH% -- relative path from view root object to this item %PATH% -- equal to %ROOT%/%RPATH% %SELF% -- displayed item value (image or attribute value) %SIZE% -- number of bytes in %SELF% %TYPE% -- type of leaf item (LINKITEM, LINKGROUPTAG, ...) %LINE% -- number of lines in the current item %POS% -- current number of siblings (starting from zero) %LEVEL% -- level in the reference structure/tree %GROUP% -- group name for item %FIELD% -- field name for item
For example, when retrieving an image in xbm format from the database, we generate the appropriate Content-Type and Content-Length MIME headers using %SELF% to retrieve the image and %SIZE% to get the size.