There are a few form decoding
function libraries for C and C++. These include the previously mentioned
uncgi
library, and Enterprise Integration Technologies Corporation's (EIT)
libcgi. Both of them are simple to use.
Let's look at an example using uncgi
(assuming the HTML form is the same as the one used in the previous
example):
#include <stdio.h>
#include <stdlib.h>
These two
libraries--standard I/O and standard library--are
used in the following
program. The getenv
function, used to access environment variables, is declared in stdlib.h.
void main (void)
{
char *name,
*age,
*drink,
*remote_host;
printf ("Content-type: text/plain\n\n");
uncgi();
Four variables are declared to store environment variable
data. The uncgi function retrieves the form
information and stores it in environment variables. For example,
a form variable called name, would be stored
in the environment variable WWW_name.
name = getenv ("WWW_name");
age = getenv ("WWW_age");
drink = getenv ("WWW_drink");
remote_host = getenv ("REMOTE_HOST");
The getenv standard library function
reads the environment variables, and returns a string containing
the appropriate information.
if (name == NULL) {
printf ("Don't want to tell me your name, huh?\n");
printf ("I know you are calling in from %s.\n\n", remote_host);
} else {
printf ("Hi %s -- Nice to meet you.\n", name);
}
if (age == NULL) {
printf ("Are you shy about your age?\n");
} else {
printf ("You are %s years old.\n", age);
}
printf ("\n");
Depending on the user information in the form, various informational
messages are output.
if (drink == NULL) {
printf ("I guess you don't like any fluids.\n");
} else {
printf ("You like: ");
while (*drink != '\0') {
if (*drink == '#') {
printf (" ");
} else {
printf ("%c", *drink);
}
++drink;
}
printf ("\n");
}
exit(0);
}
The program checks
each character in order to convert the "#" symbols to spaces. If
the character is a "#" symbol, a space is output. Otherwise, the
character itself is displayed. This process takes up eight lines
of code, and is difficult to implement when compared to Perl. In
Perl, it can be done simply like this:
This example points out one of the major deficiencies of C
for CGI program design: pattern matching.
Now, let's
look at another example in C. But this time, we will use EIT's libcgi
library, which you can get from https://wsk.eit.com/wsk/dist/doc/libcgi/libcgi.html.
#include <stdio.h>
#include "cgi.h"
The header file cgi.h
contains the prototypes for the functions in the library. Simply
put, the file--like all the other header files--contains a list of
all the functions and their arguments.
cgi_main (cgi_info *cgi)
{
char *name,
*age,
*drink,
*remote_host;
Notice that there is no main
function in this program. The libcgi library
actually contains the main function, which
fills a struct called cgi_info with environment
variables and data retrieved from the form. It passes this struct
to your cgi_main function. In the function
I've written here, the variable cgi refers
to that struct:
The variable type form_entry is a linked
list that is meant to hold key/value pairs, and is defined in the
library. In this program, form_data is declared
to be of type form_entry.
print_mimeheader ("text/plain");
The print_mimeheader function is used
to output a specific MIME header. Technically,
this function is not any different from doing the following:
print "Content-type: text/plain\n\n";
However, the function does simplify things a bit, in that
the programmer does not have to worry about accidentally forgetting
to output the two newline characters after the MIME
header.
form_data = get_form_entries (cgi);
name = parmval (form_data, "name");
age = parmval (form_data, "age");
drink = parmval (form_data, "drink");
The get_form_entries function parses
the cgi struct for form information, and places
it in the variable form_data. The function
takes care of decoding the hexadecimal characters in the input.
The parmval function retrieves the value corresponding
to each form variable (key).
if (name == NULL) {
printf ("Don't want to tell me your name, huh?\n");
printf ("I know you are calling in from %s.\n\n", cgi->remote_host);
} else {
printf ("Hi %s -- Nice to meet you.\n", name);
}
Notice how the
REMOTE_HOST
environment variable is accessed. The libcgi
library places all the environment variable information into the
cgi struct.
Of course, you can still use the getenv
function to retrieve environment information.
if (age == NULL) {
printf ("Are you shy about your age?\n");
} else {
printf ("You are %s years old.\n", age);
}
printf ("\n");
if (drink == NULL) {
printf ("I guess you don't like any fluids.\n");
} else {
printf ("You like: %s", drink);
printf ("\n");
}
free_form_entries (form_data);
exit(0);
}
Unfortunately, this library does not handle multiple keys
properly. For example, if the form has multiple checkboxes with
the same variable name, libcgi will return
just one value for a specific key.
Once the form processing is complete, you should call the
free_form_entries function to remove the linked
list from memory.
In addition to the functions discussed, libcgi offers numerous other
ones to aid in form processing. One of the functions that you might
find useful is the mcode
function. Here is an example illustrating this function:
switch (mcode (cgi)) {
case MCODE_GET:
printf("Request Method: GET\n");
break;
case MCODE_POST:
printf("Request Method: POST\n");
break;
default:
printf("Unrecognized method: %s\n", cgi->request_method);
}
The mcode function reads the REQUEST_METHOD
information from the cgi struct and returns
a code identifying the type of request.