INTRODUCTION

CgiForms is a set of classes designed to give direct and easy access to the CGI gateway and to the processing of FORMS. There are four classes: CGI, EnvVars, Fields, and HTML. And then there are three LIST classes which derive from the HTML class. The main work is done by EnvVars, Fields, and HTML, which are members of the CGI class. When the CGI class is instantiated, the system environment variables and the NAME/VALUE pairs from your FORM are retrieved, and the http Content-type header is sent out, which is by default this line:

         "Content-Type: text/html\n\n" 
      
This means that you are immediately ready to process your FORM. If you simply want to display your environment variables and your NAME=VALUE pairs, you could write the following program:
         #include "cgi.h"
         void main()
          {
           CGI cgi;       //create an instance of the CGI class
           cgi.display_env();         //list environment values
           cgi.display_fields();       //list NAME/VALUE pairs
          }
For further introductory materials, see the Basics document.
 

THE CLASSES

Class: EnvVars
Header file: environ.h
Source file: environ.cpp

  1. This class retrieves almost all of the CGI environment variables from the system. Additional environment variables can be added by the programmer, as needed.

  2. EnvVars Class Methods
    EnvVars()
    The EnvVars Class constructor establishes private pointers to the CGI environment variables, which it makes public through env_var() ; it places the content length for POST into the public: int const content_length , and the http method into the private : int method , which it makes public through cgi_method () .

    char const *env_var(int) const
    The environment variables are accessed by means of env_var(). The integer which is passed to env_var() is one of the constants defined in
           enum  ENVIRONMENT_VARIABLES { / . . . / } 
    which is found in the environ.h. These constants are simply the names of the gateway environment variables preceded by an underscore, eg. _SERVER_NAME, _REMOTE_HOST, _QUERY_STRING, _CONTENT_LENGTH, etc. To check whether an environment variable has been set and what its value is, for example the Server's Name, you would do this:
     const char *p =  env_var(_SERVER_NAME);
     if (p) { / . . . / }    // process variable
        else  { / . . . / }    // accommodate failure
        
    cgi_method ()
    This function returns one of the following three enumerated constants, which designate which http transaction method is in effect:
    EnvVars::_METHOD_UNKNOWN,
    EnvVars::_GET,
    EnvVars::_POST
    This function is primarily for internal use by the Fields class, but some prgrams may need to know what the http method is.

    display ()
    Calling display()outputs to stdout a formatted list of CGI environment values.


  3. Notes on the EnvVars Class
    The environment variables are retrieved when the class is constructed. Each time this class is constructed it goes back to the system for the environment variables. No facility has been provided for either a copy constructor or an assignment overload, since there are no vulnerable pointers or buffers in this class, i.e. no use of either malloc or new. All pointers to the environment variables point to the same memory space in the system environment: if an instance of EnvVars goes out of scope, its pointers to the environment variables are destroyed but there's no effect on the system environment space.

Class: Fields
header file: fields.h
source file: fields.cpp


  1. The Fields class retrieves the NAME/VALUE pairs output by an HTML form.

  2. Fields Class Methods
    Fields(EnvVars &)
    When a Field class is declared, it is initialized with an EnvVars reference:
    EnvVars ev;
    Fields(ev);
    The Fields class needs data from the EnvVars class in order to process the NAME/VALUE fields, in particular it needs to know the http method and (for the POST method) the value of the CONTENT_LENGTH environment variable.

    Fields(Fields &other)
    Copy constructor.

    Fields &Fields::operator=(Fields &other)
    Overloaded assignmment operator.
    This has an important use in the constructing of Field Class objects. It is used to construct new instances of the class after a first instance has been created, unless the first instance has been destroyed, in which case the constructor uses convert().

    private: convert()
    This is a private function used internally by the Field class to create an instance of the class when the First Instance of the class has been destroyed.

    char *getvalue(char *) const
    The NAME/VALUE pairs are accessed by means of this function. The char * passed to the function is the NAME of the field, as defined in the html form. The function returns a pointer to the VALUE; if NAME is not found, the function returns 0. getvalue() is case insensitive, using an internal version of strnicmp to make the comparison. Example:
    char * fld_1 = getvalue("Field_1");
    if(fld_1) { /. . . / } //process fld_1

    void reset(),     void reset(char *name)
    Because HTML forms allow duplicate instances of the same NAME, the Fields class cannot count on every field having a unique NAME. In order to accommodate this fact, each time a VALUE is found and returned by value(), a flag is set for that instance of the NAME/VALUE pair. If getvalue() is passed the same NAME again, it will search for the next instance of NAME for which the flag has not been set. The reset() function allows you to set all of the flags back to zero, should you want to go back over the NAME/VALUE pairs. The companion to this function offers added flexibility, by allowing you to reset to zero the flags for specific NAMES, while leaving the remaining flags in tact.

    void disableRetrieveFlag(),    void enableRetrieveFlag ()
    The default behavior of the Fields Class is to set a flag whenever a NAME is found and its VALUE is retrieved and then to check for that flag. If the flag is set, it looks for the next instance of NAME. (See getvalue().) You can turn off the default flag checking in getvalue() by calling disableRetrieveFlag(). If you do not have any duplicate NAMES in your FORM and if you wish to access getvalue() more than once for all or some NAME/VALUE fields, calling disableRetrieveFlag() eliminates the need to use the reset() functions.

    For the sake of completeness enableRetrieveFlag() is provided, giving you the option of re-enabling the flags, if you have disabled them.

    void display() const
    This function outputs a formatted listing of NAME/VALUE pairs to stdout. In effect, the list will appear in the browser, if you have inidicated to the browser that your are outputting an html file by sending it the "text/html" header, which is th default for CgiForms.


  3. Notes on the Fields Class
    In a FORM which uses the default method of the http protocol, which is GET, the NAME/VALUE fields are placed in the QUERY_STRING environment variable. In the POST method they are transmitted to the cgi gateway program by means of the standard input facility. Whichever method is used by the FORM, the Fields Class copies the NAME/VALUE data into an internal buffer: char *fieldstring. The field string is exhausted in the process of extracting the NAME/VALUE fields from the buffer. Unlike the EnvVars class, which can go back to the system for the CGI environment variables whenever a new instance of the EnvVars class is constructed, the Fields Class has to know whether or not the buffer has been processed when a new instance of the class is created. It knows this by means of a private static pointer to the first instance of Field. If FirstInstance is True, the class uses its overloaded assignment operator initialize subsequent instances of Field, unless the First Instance has been destroyed, in which case it uses convert(). Both an overloaded assignment operator and a copy constructor are provided for this class, because Fields uses new to create a linked list of FIELDPAIRS structures and the fieldstring character buffer.

Class: HTML
header file: html.h
source file: html.cpp


  1. The HTML class, together with the classes derived from it, is the most extensive of the classes provided by CgiForms. However, you can write a program to process a FORM without ever accessing this class. It is here for your convenience and has only one necessary task, which is to output the HTML Content-Type line: "Content-Type: text/html \n\n". But this is done automatically when you create the CGI class.

  2. The HTML class and its derived classes (TABLE, LIST) provide a set of methods which offer short-cuts to the outputting of basic HTML elements. Where methods are not provided, you use the standard functions for writing to stdout. It is recommended that you use the C++ iostream class for writing to stdout, since this is what is used in the HTML Class, and mixing iostream methods with stdio.h functions printf(), puts(), fprintf(), could possibly cause unpredicatable results.

  3. HTML Class Methods
    HTML(const char *content_type),    HTML()
    The HTML class has two constructors. The first constructor accepts a string indicating the MIME type format. When you create the CGI class, it automatically initializes its member HTML class to "text/html", unless the CGI class is itself initialized with another MIME type string. It is conceivable that you might want to output a MIME type other than "text/html". The MIME type is output only once. In subsequent instances of HTML which are initialized with MIME type strings, the MIME type strings will be ignored.

    The second constructor, which takes no MIME type string, should be used for all instantiations of this class after the first instance. The HTML Class is essentially a set of methods for creating HTML statements. Multiple instances of it can be safely declared in your program without concern for side effects, for code or data size, or for processing overhead.

    void text_out(int tag, char *text)
    This is a general purpose function for writing a text string set between opening and closing HTML tags, as in:
    <H1>This is a Heading</H>
    The HTML tag is indicated by an enumerated constant, which is defined in enum tag. This enumeration is declared in html.h but it is not a class member. The constants defined in this enumeration are some of the basic HTML tags preceded by an underscore and are as follows:
    _H1, _H2, _H3, _H4, _H5, _H6, _B, _I, _P, _BR
    These constants are indexes into the array char *tag[], found in html.cpp. You can easily extend this list, but any additional tags must be added to the end of the list, i.e. after _BR.

    void otag(int tnum) const,    void ctag(int tnum) const
    These functions output an opening (otag) or closing tag (ctag). The tag is identified by one of the enumerated constants discussed above in the description of text_out().

    void otag(const char *) const,    void ctag(const char *) const
    These functions accept character strings of tag names and create opening and closing tags from them. You might, for instance, want to create a block quote. You would first call otag("blockquote"), which would create the following tag: <blockquote> When your blockquote is complete, you would call ctag("blockquote"), which would create the closing tag: </blockquote>

    void header(const char *title) const
    This function creates the HTML file header:
    <HTML><HEAD><TITLE>title<TITLE></HEAD>

    void obody(const char *format_string = "") const
    This function creates the open body tag and includes within it any formatting attributes which are passed to it in format_string. If no format string is passed to it, the result is:
    <BODY>
    If you want, for example, a BLACK background color behind WHITE text output, you Would call the function as follows:
    obody("BGCOLOR = \"#000000\" TEXT = \"#FFFFFF\");
    This would create the following tag:
    <BODY BGCOLOR = "#000000" TEXT = "#FFFFFF">

    void footer() const
    The footer() function closes off your html file as follows:
    </BODY></HTML>


    void cbody() const,    void cHTML() const
    These functions output </BODY> and </HTML> respectively. In most cases you would use the footer() function to close off your HTML file.

Class: TABLE :public HTML
header file: html.h
source file: html.cpp


  1. The TABLE Class is derived from the HTML class and so includes all of the functionality of the HTML Class. In addition, it provides several methods specific to creating Tables.

  2. A TABLE Class object should ideally be used within a function specifically designed for the creation of that TABLE. For example:
    void maketable()
    {
    TABLE tbl;
    / . . . / //create table here
    }

    When the TABLE object is constructed, the constructor outputs the opening table tag, i.e. <TABLE>, and when the function ends and the TABLE object goes out of scope, the destructor similarly outputs the closing table tag, i.e. </TABLE>, unless the table has been closed earlier by a call to ctable(). If a Table is created inside a function containing other code, it is important to know that the open Table tag will be immediately output to stdout at the point in the code where the TABLE object has been declared. Incorrect placement of TABLE declarations and failure to take into consideration the output of the closing Table tag by the destructor can create incorrect nesting of HTML elements. For example:
      void process_form()
       {
          TABLE tbl;   // <TABLE> output to stdout
           / . . . . /  // Code not relevant to Table:  Error
          / . . . . /   // Code creating Table
          / . . . . /   // Additional Non-Table related Code
                        // TABLE Object goes out of scope and
                        // outputs closing table tag: </TABLE>
                       //  Destructor outputs second
                       //     </TABLE> 
      }
         
    The correct way to deal with this situation is as follows:
     void process_form()
      {
          / . . . . /  // Code not relevant to Table
    
         TABLE tbl;    // <TABLE> output to stdout
          / . . . . /   // Code creating Table
          tbl.ctable(); // Close Table: </Table>
    
       / . . . . /  // Additional Non-Table related Code
    
             // TABLE Object goes out of scope
            // but does not output </TABLE>
     }
    

  3. TABLE Class methods
    TABLE(),    TABLE(const char *format_string)
    The TABLE Class has two constructors. One takes a format string and the other does not. If a format string is not supplied, the constructor outputs the basic opening tag, which is simply <TABLE>. If a format string is supplied, the string is included in the tag so that the declaration TABLE table("BORDER = 2 CELLSPACING = 2"); will create the following line: <TABLE BORDER = 2 CELLSPACING = 2>

    void row_out(int cols,...)
    The row_out() function does the major work of the TABLE Class. It outputs Table data a row at a time. It takes a variable number of character pointers to Table Data. The parameter cols tells row_out how many character pointers are being passed to it. If the strings are short enough, of course, they can be placed directly in the list of arguments to the function. An example of row_out() might be:
    row_out(2, "Data for col 1", "Data for Col 2");
    This call would produce the following output:
    <tr>
    <td>Data for col 1</td>
    <td>Data for col 2</td>
    </tr>

    void format_row(char *format_string)
    This allows for the use of TR attributes ALIGN, VALIGN, and whatever may eventually be made available. A row format string remains in effect until format_row is called again. If you want to disable the format string, after it has been set, you can call format_row() with a null string: format_row("").

    void ctable()
    This function closes a Table. It does so by calling the HTML inline function: ctag("TABLE"). At the same time it sets an internal flag which eventually will let the destructor know that this table has already been closed.


  4. Notes on the TABLE Class
    The TABLE class offers a fair amount of flexibility for the creation of Tables but it leaves out a number of elements which would give full functionality to the Class. It leaves out the <TH> and <CAPTION> elements, on the assumption that these are not as frequently used as the other Table elements and that the standard HTML methods can just as easily deal with them. To create a Table Header, for instance, you could use the following code:
                   otag("TH");
                   cout << "this is my header";
                   ctag("TH");
          
    A programmer could easily extend the Table class, creating a method for headers, for instance, from the above code:
                    void header(char * format){
                     otag("TH"); cout << format; ctag("TH");
                    }
    
    The attributes assigned to a <TR> tag apply to all of the columns in the row. In its present implementation, however, the TABLE Class has no methods that allow for specifying attributes to the TD tag, a technique which enables the formatting of individual cells, i.e. a particular column in a particular row. To do this row_out() would have to be extended to handle separate format strings for individual cells. This seemed to offere little gain over direct coding of complex Tables. Here is a Table with two rows that uses the rowspan attribute in the first column of the first row:
         otag("TR");                                // start row 1
         otag("TD rowspan = 2"); cout << "item 1";  ctag("TD");
         otag("TD");  cout << "item 2";  ctag("TD");
         otag("TD");  cout << "item 3";  ctag("TD");
         ctag("TR");                                // end row 1
         row_out(2, "item 4", "item 5");            // output row 2
    
    This table is implemented in misc.cpp in the function mtable2(); a fully commented table with caption and header is implemented in make_table(), also found in misc.cpp.

LIST CLASSES
class OLIST :public HTML
class ULIST :public HTML
class DLIST :public LIST
header file: html.h


  1. CgiForms defines three LIST classes: The Ordered List, OLIST; the unordered List, ULIST; and the Definitions List, DLIST. All three classes are based on the LIST Class Template, which is defined in html.h and, like the TABLE Class, are derived from the HTML Class, and so share its functionality. The DLIST Class, however, involves a third level of derivation. It is a separately defined class which inherits the LIST class methods through derivation.

  2. Like the TABLE Class, these classes should also be implemented, where possible, from within separate functions. For, the same considerations with respect to constructors and destructors apply to these classes as apply to the TABLE Class. Please see point 2 of the TABLE Class.

  3. Apart from outputting their individual List type tags (i.e., UL, OL), ULIST and OLIST, the Ordered and Unordered lists, are exactly alike. The Definitions LIST, DLIST, shares the methods of OLIST and ULIST but adds one additional method to handle the <DT> tag.


  4. LIST Class methods.
    OLIST (),   ULIST (),   DLIST ()
    Each LIST Class constructor outputs the open tag for its particular LIST Type when its constructor is called, i.e. <UL>, <OL>, <DL>. Like the TABLE Class, each LIST class destructor outputs the closing tag for its type:
    </UL>, </OL>, </DL>.

    void item_out(char *str) const
    The item_out() function outputs the required tag for the LIST type followed by the text pointed to by str, so that unorderedlist.item_out("Item 1") yields:
    <LI>Item 1
    and define.item_out("Item 1") yields:
    <DD>Item 1

    void clist()
    This function allows you to close a list before the Class goes out of scope and has the same strategic uses as ctable() discussed in the TABLE class.

    void DT (char *term = '\0')
    This function is exclusive to the Definition List Class DLIST. It adds access to the third term of a definition List, the <DT> tag, which designates the Term which is to be defined by the <DD> element. The function takes as an argument a character pointer to the Term which is to be defined. If no argument is provided, then just the tag <DT> is output. An example DLIST might be as follows:
            DLIST dl;      // constructor outputs:  <DL>
             dl.DT("Bit");       
             dl.item_out("binary 1 or 0");
             dl.item_out("small amount");
             dl.clist();                        
    
    The resulting HTML would be:
          <DL>
               <DT>Bit
               <DD>binary 1 or 0
               <DD>small amount
          </DL> 
                                            

  5. A commented example of nested lists is implemented in makelist(), which will be found in misc.cpp. While tables cannot be nested, lists can, if care is taken to declare and close the lists at the approporiate places in your code.

  6. Notes on the LIST Classes
    The LIST Classes are formed from the LIST Class template, which is defined as follows:
    template <class type>
    class LIST : public HTML
    The <type> is one of three utility classes: OL, DL, and UL. The purpose of these three classes is to assign the necessary identifiers to the tags for each class (i.e. UL, OL, DL, LI, DD). DLIST is a separately defined class which inherits a LIST template class which takes the DD type. It is defined as follows:
    class DLIST : public LIST <DD>
    OLIST and ULIST are #defines:
    #define OLIST LIST <OL>
    #define ULIST LIST <UL>
    so that the declarations
    OLIST ol;
    ULIST ul;
    are in fact the following:
    LIST <OL> ol;
    LIST <UL> ul;
    The complete scheme is available for perusal in html.h.

Class: CGI
header file: cgi.h
source file: cgi.cpp

  1. The CGI Class is the interface for the three main classes described above (EnvVars, Fields, HTML), which are member classes of CGI. When a CGI class is instantiated, the other three classes are constructed and initialized in the proper order. All the Environment Values and NAME/VALUE fields have been read and stored, and the http Content-Type string has been output to the client.

  2. The CGI Class has been devised with an eye towards giving the programmer maximum flexibility. You can run your script directly from main(), i.e. without ever leaving main; you can derive your own CGI class from CGI; or you can do the work of your program in one or more of the three vrtual functions, processenv, processfieds, runCGI, which can be used simply by inserting your code directly into them. These functions come supplied with the minimum code necessary to satisfy compiler type-checking; they are meant to be re-written, as needed.

  3. The CGI class provides access functions to the Fields and EnvVars Classes, so that for many applications it will not be necessary to access the Fields or EnvVars Classes directly; the CGI Interface will have the facilities you need to process your FORM. However, to use the HTML Class you will need to have access to its methods.

  4. CGI Class Methods
    CGI(),    CGI(char *content_type)
    To begin with, it is relevant to know that the CGI Class declares the following classes as private members:
    EnvVars ev;
    Fields flds;
    HTML html;
    The order in which these classes are declared is significant, since EnvVars must be initialized before Fields, which requires knowledge of a number of CGI environment variables and which is, therefore, initialized with a reference to EnvVars. The full CGI constructor is as follows:
    CGI::CGI() :flds(ev), html("text/html"){ }
    EnvVars is initialized using the default constructor; a reference to it is passed to Fields; and then the HTML class is initialized with the string "text/html", which is why, when the first CGI object is instantiated, the http header defaults to "Content-Type: text/html", unless another string is passed to the constructor, in which case, HTML is initialized with that string:
    CGI::CGI(char *content_type) :flds(ev), html(content_type) { }


    void display_fields() const
    This function outputs a formatted list of NAME/VALUE pairs.

    void display_env() const
    This function outputs a formatted list of CGI environment variables.

    char *getfieldvalue(char *name)
    When this function is passed a pointer to the NAME of a NAME/VALUE pair, it returns a pointer to the VALUE.

    Given an HTML INPUT field with NAME = "Phone" and VALUE = "555-1212", the browser will send "Phone=555-1212" to your CGI script. You could then make the following function call:
    char *tel = getfieldvalue("Phone")
    This would assign "555-1212" to tel.

    getfieldvalue() is defined as follows:
    inline char const *CGI::getenv_var(int name) const
    { return flds.getvalue(name); }
    Thus, it gives the CGI Interface Class access to Field::getvalue().

    void zerofldflags()
    In some FORMS, there is more than one instance of a NAME, which may have several VALUES. This is possible, for instance, with the Checkbox type of the Input tag:
    DB 1<input type="checkbox" name="dbase" value = "db1"> <br>
    DB 2<input type="checkbox" name="dbase" value = "db2"> <br>
    DB 3<input type="checkbox" name="dbase" value = "db3"> <br>

    When the Field object retrieves a VALUE for an instance of a NAME, in this example "dbase", it sets the field's retrieved flag = 1, so that it will not retrieve the same VALUE the next time you request the VALUE for "dbase". In such cases you must call zerofldflags(), in order to zero out the retrieved flags or else the VALUES of duplicate NAMES whose retrieved flags = 1 will no longer be available. The Field Class provides a flexible set of alternative methods, which allow for resetting individual flags to zero and disabling all the flags for programs which do not have duplicate NAMES. See Fields::reset(char *name), Fields::disableRetrieveFlag(), and Fields::enableRetrieveFlag().

    char const *getenv_var(int name) const
    CGI::getenv_var() provides the same service for the environment variables as CGI::getfieldvalue() provides for the NAME/VALUE fields. Here, however, the parameter name is an integer constant defined in environ.h, which takes the form of the CGI gateway environment variable identifier, all upper case, and preceded by and underscore, as in _QUERY_STRING and _CONTENT_LENGTH. It returns a char * to the environment variable. Like its counterpart in the Field Class, it is an access function; it provides the CGI Interface Class access to the EnvVars method which returns pointers to CGI Gateway Environment Variables:
    inline char const *CGI::getenv_var(int name) const
       { return ev.env_var(name); }
    For additional information on this function, you may consult the discussion of EnvVar::env_var(), the document on basics, and the cgi.h file.

    virtual int processfields(),   virtual int processenv()
    You will find these functions in the source file cgi.cpp. They have been left essentially empty. You may re-write them for the CGI Interface Class, inserting your own code into them, as needed. Or, you may derive your own class from the CGI class and create new versions of these functions, again as needed. An example of derivation is given in the file mycgi.cpp.

    The names of these functions are self-explanatory. They are designed to give you separate program space for processing Environment Variables and NAME/VALUE fields, whether or not you choose to use the CGI Class as a base class. However, you may create an entire program wholly within the main() function, if the program lends itself to a minimal implementation.

    virtual int runCGI ()
    In the case of a program which uses the CGI Class as a base class for derivation, you might find it useful to have a function from which to run the various aspects of the program, i.e. runCGI().

    Fields *getfieldsptr()
    This function returns a pointer to the Fields member of the CGI Class. This will give you access to the Fields Class public members and could be useful, for instance, if you want to call Fields::disableRetrieveFlag() or Fields::reset(char *), for which there are no access functions in the CGI Class.

    EnvVars *getenvptr()
    This function returns a pointer to the EnvVars member of the the CGI Class. This will give you access to the public members of the EnvVars Class, in particular to EnvVars::cgi_method () and to EnvVars::content_length, which will tell you, respectively, whether the FORM method was POST or GET and, if POST, what the content length was.


MISCELLANEOUS FUNCTIONS
source file: misc.cpp
header file: cgiform.h

  1. The source file misc.cpp contains several example functions for creating lists, a function for constructing URL's and paths, and an internal, required function for doing case insensitive string comparisons. The header file has the necessary declarations for these functions as well as the ENDL define which is used in various output statements throughout CgiForms.

  2. The Miscellaneous Functions
    int __strnicmp(const char *str1, const char *str2, size_t len)
    Internally required case insensitive string comparison, which like all C string comparisons returns 0 on success.

    char *make_path(int parms, ...)
    This function takes a variable number of character pointers to strings that make up an address or path; the parms argument is an integer indicating the number of parameters passed to it. The strings must be passed in the order in which they will appear in the path or the address, the leftmost element first, etc. From the strings make_path() will create the path or URL. It recognizes a port address by the preceding semi-colon, as in :80. This means that the port address has to be constructed before being sent to make_path(); see the example in myCGI::processenv() in the file mycgi.cpp

    void make_table(),   void mtable2(),   void makelist()
    Examples of using the LIST and TABLE Classes to make lists and Tables. It is recommended that your programs implement each table and list inside its own separate, self-contained function, as in these examples.


    Class: myCGI
    source file: myCGI.cpp
    header file: none
    1. myCGI is an example a class derived from CGI, which uses the virtual functions run(), processenv(), and processfields().
    2. myCGI Class methods
      int processenv()
      This function demonstrates how to access environment variables, using the CGI Interface Class and how to construct a URL using makepath()
      int processfields()
      This function demonstrates how to retrieve VALUES from NAME/VALUE fields using the CGI Interface Class and how to construct a nested list.
      int run() Implements the CGI run() .method.


    Return to top