WebÞing

CGI++ Programmers Guide

Copyright © Nick Kew, 1997.

This document describes briefly the CGI++ classes and their public methods. It assumes some basic familiarity with C++, CGI, HTML and HTTP, but an in-depth understanding of all these should not be necessary.

Table of Contents

  1. The FEP (Form Element) Class
    1. Constructors/Destructor
    2. Setting the value of an Element
    3. Setting (and accessing) the Options in a menu or radio group
    4. Reading the value of an element
    5. Accessing, Saving and Displaying element values in WWW formats
    6. Accessing the form_element directly (low-level access)
  2. The FORM class
    1. Constructor/Destructor
    2. Accessing Form data
    3. Declaring Form Data
      1. Format of Form Element Definitions.
    4. Displaying a Form
    5. Diagnostic/Debugging Functions
  3. The CGI Class
    1. Constructor/Destructor
    2. FORM data:
      1. Reading and Parsing
      2. FORM data: Saving and restoring state
      3. FORM data: miscellaneous.
    3. Environment Data and HTTP Headers
      1. CGI Environment Variables
      2. HTTP General Headers
      3. HTTP Request Headers
      4. HTTP Entity Headers
      5. Other Headers
    4. Parsing Headers and Environment.
      1. Parsed Headers
    5. HTTP Authentication
    6. Debugging Facilities
      1. Interactive Debugging Mode
  4. Accessory Functions
    1. HTML and WWW Escaping
    2. Persistence: Classes to Save and Restore State
    3. CDATA, charp
  5. The Form Elements (half-baked descriptions).
    1. form_element
    2. form_string
    3. form_options
    4. form_mc
    5. form_sized
    6. form_checkbox
    7. form_select_multiple
    8. form_hidden
    9. form_password
    10. form_input
    11. form_textarea
    12. form_radio
    13. form_select
    14. form_submit
    15. form_imagemap_coord
    16. form_imagemap
    17. form_file
    18. form_unset

1: The FEP (Form Element) Class

FEP is a wrapper for the form element hierarchy.   For most operations
you should use FEP rather than addressing the elements directly, but
this is not enforced.

[Table of Contents]

1.1: Constructors/Destructor

FEP() ;
FEP(form_element*) ;
FEP(const FEP&) ;
~FEP() ;
void destruct() ;

The first constructor is required by the Map container class, and
should not generally be used by programmers.
The second gives the notation
	form["name"] = new form_xyz(args) ;
when using the CGI or FORM classes.   You should NOT delete the memory
allocated in this operation - FORM::~FORM will do it automatically.
The third copies only the pointer - not the data.

The destructor does not free the memory allocated for the form element.
If the element is used in a FORM or CGI object, this is handled
automatically as described above.   However, if you create freestanding
FEPs which are not part of a FORM or CGI, you must call destruct()
to avoid a memory leak.

[Table of Contents]

1.2: Setting the value of an Element

Meaningful for all elements
void set(String&) ;
void set(const char*) ;
form_element& operator=(form_element&) ;
void add(String&) ;
void add(const char*) ;

Meaningful only for particular elements:
void unset(String&) ;
void clear() ;
void add_header(String&, String&) ;
const String& filename(const String&) ;

set() will set the value of a form element (even non-String elements).
add() appends its argument to the value already set.

In the case of a string element, set() will overwrite any existing
value.   For a multivalued element (SELECT MULTIPLE) it will instead
add the new value to the currently selected set.   Additional methods
unset (opposite of set()) and clear() (clear all values) are therefore
provided, or you can access the element directly through "multi()".

A FILE element is an entire MIME entity, and may have headers and
will have a filename (the value is considered to be the contents
of the entity, so that all the accessor methods lake as_text/as_html
work as expected).   The filename() and add_header() methods are
really internal to CGI++, but are also available to programmers.

[Table of Contents]

1.3: Setting (and accessing) the Options in a menu or radio group

String& operator[](String&) ;
String& operator[](const char*) ;

foo["internal"] = "external" will set the element to display the
option "external" in a browser and return "internal" to CGI if it
is selected in the form.   The syntax is identical for menus
(SELECT, SELECT MULTIPLE) and RADIO groups.

[Table of Contents]

1.4: Reading the value of an element

String& as_text() ;

as_text() returns all string-valued elements as-is.   For other elements
it returns a text string summarising the contents, and the value is
accessed by one or more of the following methods meaningful only for
certain elements:

Bag& multi() ;
Map& headers() ;
const String& filename(const String&) ;
const int checked() ;
const int x() ;
const int y() ;

multi() returns the value of a SELECT MULTIPLE element.

headers() and filename() return header data for a FILE element
(filename() can be called without an argument to read the value).

checked() returns zero (unchecked) or nonzero (checked)
for a CHECKBOX element.

x() and y() are the coordinates returned by an IMAGEMAP click
(and will return -1 if unset - typically if the map wasn't clicked).

[Table of Contents]

1.5: Accessing, Saving and Displaying element values in WWW formats

void print(const String&, ostream&) ;
String& encode(const String&) ;
CDATA& render(const String&) ;
CDATA& as_html() ;

Form elements do not hold their own name, so you must pass it to
the following methods.   For example, if "foo" is a plain input
field with size 12 and value "Hello", foo.render("foo") will return
the CDATA string
<input name="foo" value="Hello" size=12>

as_html() returns the value in a format suitable for HTML display
(usually just an HTML-escaped version of as_text()).
render() returns and print() prints the complete HTML to display the
form element as currently defined.

encode() returns the element URLencoded, for saving to file or for
use in an HTTP request to another server.

[Table of Contents]

1.6: Accessing the form_element directly (low-level access)

const form_element* operator()() const ;
form_element* operator()() ;

If you need to use these, the chances are there's something wrong with
the implementation of FEP.   But they're available, anyway.

[Table of Contents]

2: The FORM class

The FORM class defines the FORM structure as a collection of FEPs
(Form Elements) with methods to create, access and render them.

[Table of Contents]

2.1: Constructor/Destructor

These manage the Form Elements (FEPs), including deleting them in
the destructor.   Neither take arguments, and both may be ignored
by programmers.

[Table of Contents]

2.2: Accessing Form data

FEP& form::operator[](String& name) ;
FEP& form::operator[](const char* name) ;

Form element "foo" is accessed as
	form["foo"]
which is both an lvalue and an rvalue.


[Table of Contents]

2.3: Declaring Form Data

void form::define(int, ...) ;
void form::set_template(const String&) ;
new form_element( ) ;

void set_delimiter(const char) ;

If you are only ever going to read form data raw (as plain strings), you
can skip declaring it altogether.   However, for more advanced uses, you
must declare your elements so CGI++ knows how to treat them.   These
cases include:
* Anytime you want to use CGI++ to display the elements, it needs to know
  which particular HTML rendition to use.
* Anytime you want to read form elements whose return value is not a plain
  character string, such as SELECT MULTIPLE or IMAGEMAP.

define() may declare all the elements of a form in a single call.   The
first argument (int) is the number of elements define() expects, subsequent
elements are character strings as described below.

set_template() is primarily used by define, but is also available to
programmers to declare a single form element.

You can also use new() directly, since FEP has a constructor taking
form_element* as argument.

[Table of Contents]

2.3.1: Format of Form Element Definitions.

Each form element definition is a single character string, comprising
two to five fields which are parsed internally.   The fields are separated
by colon (':'), but this may be changed using set_delimiter() if
(for example) you need to use the colon yourself.   The format of a
field definition is:
	"name:type:value:arg1:arg2"
where name is the name of the element and type its type.
Other arguments depend on the type (see the individual Form Elements)
but default usage sets "value" to be the default (String) value, and
arg1/arg2 to be sizes (e.g. HTML size/maxlength) for printing.

[Table of Contents]

2.4: Displaying a Form

Arguments to the following are all char* strings.

const CDATA& start(action, method, enctype) const ;
const CDATA& submit(label) const ;
const CDATA& reset(label) const ;
const CDATA& end() const ;
const CDATA& render(element_name) ;

start() opens an HTML form: action is the URL (relative or absolute)
to be called, method and enctype refer to the corresponding HTML
attributes and are both optional.   If not set, method defaults
to POST and enctype will not be set (so by the rules of HTML
it is implicitly "application/x-www-form-urlencoded" - which
is in any case the only enctype most browsers can deal with).

end() closes a form.

submit() and reset() are provided as separate function calls to
enable you to print these buttons without declaring them
explicitly as form elements.   A RESET button never returns a
value to CGI, and a SUBMIT button may do with some browsers but
this is ignored by most CGI programs, so it seems inappropriate
to declare them as form elements (although there is also a
"form_submit" element if you wish to use it).   The Labels
are optional in both cases.

render() returns a the form element (or group of elements)
form[element_name], rendered in HTML with all appropriate values,
labels and defaults selected.
See the Form Elements descriptions for details.

[Table of Contents]

2.5: Diagnostic/Debugging Functions

const String& dump_as_text() ;
const CDATA& dump_as_html(action, method, enctype) ;

These will print the entire contents of the form, either as a
plain text list of elements and their values, or an HTML table.
In the latter case, the table has three columns:
	name value rendition
The first two correspond to the plain text dump, while the third
shows how CGI++ will render this form element.   The form is live,
and (provided at least one SUBMIT button or IMAGEMAP is defined)
may be submitted back to your CGI from the HTML dump.   See the
"demo.cc" program for an example of usage.

Arguments to dump_as_html() are the same as to start()

[Table of Contents]

3: The CGI Class

The CGI class provides access to Form data and Environment data,
with a full range of functions.   It inherits from FORM, so all
the methods described above are available to a CGI.

[Table of Contents]

3.1: Constructor/Destructor

As with FORM, these are limited to internal memory management and
may be safely ignored by programmers.

[Table of Contents]

3.2: FORM data:

[Table of Contents]

3.2.1: Reading and Parsing

void form()
is the key method which handles reading and parsing form data.

(1) If REQUEST_METHOD is not set, it will go into interactive
    debugging mode as described below.
(2) Otherwise it doesn't look at the method.   There is (already)
    no ambiguity between GET, HEAD and POST, and passing of FORM
    data via PUT, DELETE, OPTIONS, TRACE and extension methods
    is not defined, so it was considered appropriate to accept
    _all_ known protocols for passing form data
(3) Any data passed in QUERY_STRING will be parsed.   This
    handles the GET and HEAD methods.
(4) Any document body supplied with a content-type of
	application/x-www-form-urlencoded	(standard Form)
    or
	multipart/form-data			(Netscape file upload)
    will be parsed.   This handles POST.
(5) Any document body supplied with a different type will not
    be parsed, but is available raw to programmers via the
    "body()" method.

[Table of Contents]

3.2.2: FORM data: Saving and restoring state

const int readfrom(filename) ;
const int saveto(filename) ;

The filename argument is a char* string: these methods handle opening,
locking and closing internally via the FileStream class.   Errors are
handled internally - check cerr for diagnostics if they fail.

[Table of Contents]

3.2.3: FORM data: miscellaneous.

char const*const body() const ;
Returns document body raw, unparsed.   Only valid when the document
is not a valid CGI type and cannot be parsed.

Parsed form data is accessed as cgi[name] (operator[] inherited from
class FORM - see above).   Data passed from standard WWW browsers
is always parsed.

[Table of Contents]

3.3: Environment Data and HTTP Headers

const char*const cenv(name) ;
String& env(name) ;

Return an environment variable.   They are not quite equivalent to
getenv() because CGI keeps an internal cache.   In partiticular,
values returned by env() may be used as lvalues to fake environment
variables.

CGI++'s internal cache is declared static, so all accesses (including
"faked" changes) are global.

[Table of Contents]

3.3.1: CGI Environment Variables

Accessors returning "String&" are provided for all CGI/1.1 environment
variables.   See the header file CGI.h for details.

[Table of Contents]

3.3.2: HTTP General Headers

Accessors returning "String&" are provided for all HTTP/1.1 general
headers.   See the header file CGI.h for details.

[Table of Contents]

3.3.3: HTTP Request Headers

Accessors returning "String&" are provided for all HTTP/1.1 request
headers.   See the header file CGI.h for details.

[Table of Contents]

3.3.4: HTTP Entity Headers

Accessors returning "String&" are provided for all HTTP/1.1 entity
headers.   See the header file CGI.h for details.

[Table of Contents]

3.3.5: Other Headers

Two headers not in any spec but commonly used in a CGI environment
are supported in the manner of all the others by CGI++:

String& cookie() ;
String& script_filename() ;

[Table of Contents]

3.4: Parsing Headers and Environment.

String& key_val(input, key, eq, end) const ;
const int word_match(input, key) const ;

"input" is a String, typically returned by env() or one of the
CGI environment variable or HTTP header accessor methods.
"key" is a char* string to match within the input
The "eq" and "end" arguments to key_val are optional delimiters of
type char, defaulting to '=' and ';' respectively.

key_val() searches the input string for a match on
	Regex("key=[^;];")
and returns the match if any
(substitute your own values for '=' and ';' if appropriate)

word_match() looks for a key in the input.   The key may not be immediately
preceded or followed by an alphanumeric character - somewhat like
Perl's \b (and exactly as many programmers would wish \b to behave).
Hence word_match("foobar","bar") returns 0 (no match) while
word_match("foo.bar","bar") returns 1.

[Table of Contents]

3.4.1: Parsed Headers

Only a token few variables (other than QUERY_STRING of course)
are parsed by CGI++ in the current release.   All of the following
are front ends to the parsing methods described above, and take
a char* string as argument:

const int content_language(arg) ;
const int if_match(arg) ;
const int if_none_match(arg) ;
const int accept(arg) ;
const int accept_charset(arg) ;
const int accept_encoding(arg) ;
const int accept_language(arg) ;
String& cookie(arg) ;

[Table of Contents]

3.5: HTTP Authentication

void authenticate(authtype, realm) const ;

Prints a 401 Authentication challenge with the authtype and realm
supplied.   Note that this is not useful unless the CGI program
is defined as protected in the HTTPD's configuration - see the
CGI FAQ for more explanation.   I expect to add much fuller
handling of authentication in a future release.

A typical usage of this authentication is
if ( ! document.is_authorised( cgi.remote_user()) ) {
  cgi.authenticate("Basic", "myrealm") ;
  exit(0) ;
}
which provides an easy implementation of different protections
for different documents.

[Table of Contents]

3.6: Debugging Facilities

const String& dump_as_text() ;
const CDATA& dump_as_html(action, method, enctype) ;

These methods extend those of the parent class FORM by printing
environment data in addition to Form data.   Environment data is
taken from CGI++'s cache, and so will show "faked" environment
variables (if any - see above) as well as real values.

[Table of Contents]

3.6.1: Interactive Debugging Mode

Any program using the method CGI::form (read and parse form data) 
will enter debugging mode automatically if called from the commandline.
This mode permits you to enter your own Form and Environment data,
inspect the existing data (via dump_as_text() ) and to save/restore
state to/from file.

[Table of Contents]

4: Accessory Functions

[Table of Contents]

4.1: HTML and WWW Escaping

www_escaped_value = www_escape(value) ;
value = www_unescape(www_escaped_value) ;
html_escaped_value = html_escape(value) ;

These work with String&, const char* or const String&.
String& arguments will be modified in situ; others will return
a modified copy.

[Table of Contents]

4.2: Persistence: Classes to Save and Restore State

Classes Istream and Ostream provide simple but safe I/O management
for the readfrom/saveto methods of CGI.   They are derived from
ifstream and ofstream respectively, and so support all normal
file I/O, but add locking and error reporting in a manner
suitable for most CGI applications.

[Table of Contents]

4.3: CDATA, charp

These are simple typedefs:

CDATA is a String, and will not change until and unless a (major)
new release of CGI++ supports SGML classes.

charp is char*, and serves no useful purpose (it did in an early prototype)

[Table of Contents]

5: The Form Elements (half-baked descriptions).

Note that the preferred public interface to these is through FEP, but
this is not rgidly enforced by CGI++.

[Table of Contents]

5.1: form_element

Purpose: virtual base class for all Form Elements
Public Base Classes:
    None
Constructors:
    form_element() ;
    form_element(FEP) ;			Provides convenient universal
					conversion with strong type-checking
Public Methods:
(Key to first column methods which must be defined by derived classes:
	+ denotes a pure virtual method
	- denotes a method which generates a runtime error
)

General Methods
+   void set(String&) ;			sets value where appropriate
    void set(const char*) ;		calls set(String&)
    void add(String& s) ;		calls set()
    void add(const char* p) ;		calls add(String&)
    void print(const String&,		prints the value returned
			ostream&) ;	by render() on an ostream
+   String& as_text() ;			returns raw value where appropriate
    CDATA& as_html() ;			HTML-escapes an as_text() value
+   String& encode() ;			URL-encodes the value
+   CDATA& render(const String&)	Returns an HTML rendition of the
					element, with the NAME as supplied.
					This is the key to using CGI++ for
					object-oriented printing of forms.
    form_element&
		operator=(const char*)	Another way to call set()
    const int checked()			Yes/no flag (checkbox)

Some methods which are only required for multipart forms:
-   void add_header(String&, String&)	Sets a MIME content header
					(should probably not be public).
    const String&
	filename(const String& =NULL)	Set/read filename (for FORM_FILE)
    Map& headers()			Content Entity Headers

[Table of Contents]

5.2: form_string

Purpose:
    virtual base class for all form elements whose VALUE is a string
Public Base Classes:
    form_element
Constructors re-defined:
    form_string(String&)		Sets value
Public methods implemented or re-defined:
    void set(String&)			Sets value
    void add (String&)			Appends to value
    String& as_text()			Returns value
    String& encode(const String&)	Returns URLescaped value
Comment:
    The "value" is used differently for some elements:
    IMAGEMAP - URL for image to be displayed
    FILE - The document body of the uploaded file

[Table of Contents]

5.3: form_options

Purpose:
    Virtual base class for form elements having a MAP structure
    between internal and external representations.  Specifically,
    form_select, form_select_multiple and form_radio
Public Base Classes
    MAP (container class - String-String associative array)
Constructor:
    form_options()			Constructs null Map
Public Methods:
    String& operator[](const char*)	Extends [] notation from
					String to const char*

[Table of Contents]

5.4: form_mc

Purpose:
    Virtual base class for form elements having a MAP structure and
    a unique Value (form_select and form_radio)
Public Base Classes:
    form_string (form_element)
    form_options (MAP)
Constructors / Public Methods:
    (only those of the parent classes)

[Table of Contents]

5.5: form_sized

Purpose:
    Virtual Base class for all form elements with author-defined dimensions
    (all dimensions are optional)
Public Base Classes:
    form_string (form_element)
Constructor:
    form_sized(String& value, const String& size1, const String& size2)
			"value" is passed to the parent form_string,
			the other args are dimensions, and are optional
			(defaulting to unset)
Public Methods:
    (only those of parent classes)
Comment:
    The interpretation of the size differs between the derived classes:
    INPUT/HIDDEN/PASSWORD/FILE		size and maxlength
    TEXTAREA				rows and cols
    IMAGEMAP				width and height

[Table of Contents]

5.6: form_checkbox

Purpose:
    "CHECKBOX" element
Public Base Classes
    form_element
Public Methods
    void set(String&)			any non-null value is ON
    const int checked()			returns nonzero for ON
    String& as_text()			returns "ON" or null
    CDATA& render(const String&)	returns an HTML checkbox, with name as
					supplied, and CHECKED or not according
					to the current value
    String& encode(const String&)	URLescapes "NAME=" or "NAME=ON" pair

[Table of Contents]

5.7: form_select_multiple

Purpose:
    SELECT MULTIPLE form element
Public Base Classes:
    form_element
    form_options (MAP)
Constructor:
    form_select_multiple(String&)	Selects the value passed
Public Methods:
    Bag& value()			Returns current selection
    void set(String&)			Adds the value to current selection
    void unset(String&)			Removes from current selection
    void clear()			Clears current selection
    String& as_text()			Comma-separated list
    CDATA& as_html()			HTML unordered list (escaped)
    CDATA& render(const String&)	Returns an HTML SELECT MULTIPLE input
					with the NAME supplied and current
					selection set.
    String& encode(const String&)	Returns URLencoded rendition (as
					passed by a browser, with the NAME
					supplied repeated for each VALUE)
[Table of Contents]

5.8: form_hidden

Purpose:
    Hidden field form element
Public Base Classes:
    form_string (form_element)
Public Methods:
    CDATA& render(const String&) ;	Returns an HTML hidden field input
					with the NAME passed and current value

[Table of Contents]

5.9: form_password

Purpose:
    Password field form element
Public Base Classes:
    form_sized (form_string(form_element))
Public Methods:
    CDATA& render(const String&) ;	Returns an HTML hidden field input
					with the NAME passed and current value,
					and SIZE and MAXLENGTH if set.
[Table of Contents]

5.10: form_input

Purpose:
    Standard text input field
Public Base Classes:
    form_sized (form_string(form_element))
Public Methods:
    CDATA& render(const String&) ;	Returns an HTML input field
					with the NAME passed and current value,
					and SIZE and MAXLENGTH if set.

[Table of Contents]

5.11: form_textarea

Purpose:
    Multiline text input field
Public Base Classes:
    form_sized (form_string(form_element))
Constructor:
    form_select_multiple(String& contents, String& rows, String& cols)
Public Methods:
  CDATA& render(const String&) ;	Returns an HTML <textarea> of size
					ROWS x COLS, with the NAME passed,
					and containing the current contents.

[Table of Contents]

5.12: form_radio

Purpose:
    A group of radio buttons
Public Base Classes:
    form_mc (form_options, form_string(form_element))
Constructor:
  form_radio(String& value, const String& sep ="<br>")
					The separator is used between the
					elements when rendered: the default
					"<br>" aligns them vertically.
					Other reasonable values include
					for example " " or "</td><td>".
Public Methods:
  void separator(String& sep)		Sets the separator
  CDATA& render(const String&)		Returns a series of HTML radio buttons,
					whose values and labels are determined
					by the form_options Map.   They are
					separated by the "sep" field.   The
					button taking the current value (if
					any) is checked.

[Table of Contents]

5.13: form_select

Purpose:
    A popup menu
Public Base Classes:
    form_mc (form_options, form_string(form_element))
Public Methods:
    CDATA& render(const String&)	Returns an HTML <SELECT> menu, whose 
					options and their labels are determined
					by the form_options Map.   The option
					taking the current value (if any)
					is checked.
[Table of Contents]

5.14: form_submit

Purpose:
    A Submit Button
Public Base Classes:
    form_string(form_element)
Public Methods:
    String& render(const String&)	Returns an HTML submit button, with
					the name supplied and value (label)
					the current value.

[Table of Contents]

5.15: form_imagemap_coord

Purpose:
    This is a semi-private class used by form_imagemap, in order to
    read the coordinates supplied to CGI from a click on an imagemap.
    It should normally only be accessed through a form_imagemap.


[Table of Contents]

5.16: form_imagemap

Purpose:
    An Image Map
Public Base Classes:
    form_sized(form_string(form_element)))
Constructor:
    form_imagemap(
	String& name,			URL (relative or absolute) of
					the image file.
	String& width, String& height)	Optional width/height arguments
Public Methods:
  const int x() const			The x-coordinate of a click
  const int y() const 			The y-coordinate of a click
  CDATA& render(const String&)		Returns an HTML imagemap, with 
					the name supplied and attributes
					defined.
  String& as_text()			Returns both x and y
  String& encode(const String&)		Encodes both x and y

[Table of Contents]

5.17: form_file

Purpose:
    A File Upload Field
Public Base Classes:
    form_sized(form_string(form_element)))
Public Methods:
  CDATA& render(const String&)		Returns an HTML file upload field
					with the name supplied and current
					size attributes(if any).
  CDATA& as_html()			Returns the text both html_escaped
					and preformatted.
  Map& headers()			Returns any Entity headers supplied
					by the browser (excluding the
					Content-Disposition).

[Table of Contents]

5.18: form_unset

Purpose:
   Internal - this is used by FORM/CGI to initialise form elements
   not declared by the programmer.   You may get a memory leak if
   you use it.
[Table of Contents]