GNU CGI Library in C (GCGI)
[ releases | features | installation |
api | examples | debugging |
history | who ]
The GCGI library implements NCSA's Common Gateway Interface specification along with the extensions that were defined in RFC2388. GCGI is released under the GNU Lesser General Public License.
Releases:
Unpack the gcgi-0.9.5.tar.gz:
$ tar xvfz gcgi-0.9.5.tar.gz
$ cd gcgi-0.9.5
Configure the library:
$ ./configure
To build GCGI with encryption support, run configure like this:
$ ./configure --with-openssl
Build the gcgi library:
$ make
This should create the static library file, libgcgi.a in the src subdirectory.
If you want to make the library available to the rest of the system:
$ su
# make install
Otherwise, copy the library and the gcgi.h header file somewhere convienent. For the following example, the library and header were copied into the same directory as the program being built against it. First compile your program and then link against GCGI like this:
$ gcc -g -Wall -c example-prog.c
$ gcc -g -Wall -o example-prog -L. example-prog.o -lgcgi
and if you built with OpenSSL, link like this:
$ gcc -g -Wall -o example-prog -L. example-prog.o -lgcgi -lm -lssl -lcrypto
A set of example programs will also be built in the examples/ directory. There are example HTML forms in the examples subdirectory to use with the example programs. These should give you a good idea how to use GCGI's funtions.
API:Initialization Functions
gcgiResultType initCgi( void )
This function must be called before any interaction with the GCGI library. It will
initialize the GCGI data structures and parse the input from the web server. The
function returns GCGISUCCESS if it is able to instantiate the
CGI structures and parse the input, and GCGIFATALERROR otherwise.
void freeCgi( void )
This function must be called after use of GCGI has been completed. It will free the
memory that GCGI is using.
gcgiResultType gcgiSetLimits(size_t fieldLimit, size_t queryLimit)
This function must be called before initCgi(). It will
set two limits internally for the GCGI library: 1) the fieldLimit will cause GCGI to truncated
any single MIME part of an RFC2388 query to this numebr. It applies to all MIME parts in
the CGI query. 2) the queryLimit is the maximum data the GCGI library will read for the
entire query. These limits only apply to RFC2388's multipart/form-data. If either or both of the
limits are set to 0, then GCGI does not limit the incoming query with that limit. The
function returns GCGISUCCESS if the limits are successfully set.
Data-Fetching Functions
char *gcgiFetchEnvVar(int env)
Returns a string containing the environment variable specified as a parameter, and a NULL
pointer, otherwise. The available environment variables are listed below.
gcgiResultType gcgiFetchInteger(char *field, int *ret, int defaultRet)
This function returns an integer in the ret parameter for the field specified
in the HTML form by field. Upon success, GCGISUCCESS
is returned, and if the field is not present, then ret contains the value
given in defaultRet and GCGIFIELDNOTFOUND is returned.
If there is more than one form field of the same name, this funtion will always return the first
value submitted by the browser.
gcgiResultType gcgiFetchIntegerNext(char *field, int *ret, int defaultRet)
This function is identical to gcgiFetchInteger() except that if there are
multiple form elements of the same name, this function will return succeeding values if it is called
repeatedly. So, on the first call it returns the first instance of the form field, on the second
call, it would return the second instance, etc. Once all of the values have been iterated through,
the function will return GCGIFIELDNOTFOUND. The iteration can be started
over by calling gcgiResetMultipleField().
gcgiResultType gcgiFetchDouble(char *field, double *ret, double defaultRet)
This function returns a double in the ret parameter for the field specified
in the HTML form by field. Upon success, GCGISUCCESS
is returned, and if the field is not present, then ret contains the value
given in defaultRet and GCGIFIELDNOTFOUND is returned.
If there is more than one form field of the same name, this funtion will always return the first
value submitted by the browser.
gcgiResultType gcgiFetchDoubleNext(char *field, double *ret, double defaultRet)
This function is identical to gcgiFetchDouble() except that if there are
multiple form elements of the same name, this function will return succeeding values if it is called
repeatedly. So, on the first call it returns the first instance of the form field, on the second
call, it would return the second instance, etc. Once all of the values have been iterated through,
the function will return GCGIFIELDNOTFOUND. The iteration can be started
over by calling gcgiResetMultipleField().
gcgiResultType gcgiFetchString(char *field, char *ret, int max)
This function returns a Null-terminated string in the ret parameter for the
field specified in the HTML form by field. If the input is more than
max characters long, then the string will be truncated.
Upon success, GCGISUCCESS is returned, and if the field is not present, then
GCGIFIELDNOTFOUND is returned.
If there is more than one form field of the same name, this funtion will always return the first
value submitted by the browser.
gcgiResultType gcgiFetchStringNext(char *field, char *ret, int max)
This function is identical to gcgiFetchString() except that if there are
multiple form elements of the same name, this function will return succeeding values if it is called
repeatedly. So, on the first call it returns the first instance of the form field, on the second
call, it would return the second instance, etc. Once all of the values have been iterated through,
the function will return GCGIFIELDNOTFOUND. The iteration can be started
over by calling gcgiResetMultipleField().
gcgiResultType gcgiFetchStringNoNewLines(char *field, char *ret, int max)
This function is identical to gcgiFetchString() except that newlines are
stripped out of the input and replaced with a space. The function will remove either
"\r\n" or "\n" sequences.
gcgiResultType gcgiFetchStringNoNewLinesNext(char *field, char *ret, int max)
This function is identical to gcgiFetchStringNext() except that newlines are
stripped out of the input and replaced with a space. The function will remove either
"\r\n" or "\n" sequences.
gcgiResultType gcgiFetchData(char *field, char *ret, int max, MimeType *type, char **subtype, MimeEncoding *encoding, char **filename, int *truncated)
This function will return a block of data into the ret parameter.
It is useful for form elements, such as file uploads, which may contain binary data. If the
data is larger than max then it will be truncated to
max bytes. The MIME type, subtype, encoding and filename will be returned if
available. For the subtype and filename parameters, you must pass in a pointer to a character string
and you must free these variables when you are done with them. If the data is not available, they
will be NULL. If this MIME part was truncated because you set input limits with
gcgiSetLimits(), then the truncated flag will be set.
Upon success, GCGISUCCESS is
returned, and if the field is not present, then GCGIFIELDNOTFOUND
is returned.
gcgiResultType gcgiFetchDataNext(char *field, char *ret, int max, MimeType *type, char **subtype, MimeEncoding *encoding, char **filename, int *truncated)
This function is identical to gcgiFetchData() except that if there are
multiple form elements of the same name, this function will return succeeding values if it is called
repeatedly. So, on the first call it returns the first instance of the form field, on the second
call, it would return the second instance, etc. Once all of the values have been iterated through,
the function will return GCGIFIELDNOTFOUND. The iteration can be started
over by calling gcgiResetMultipleField().
gcgiResultType gcgiFieldLength(char *field, int *ret)
This function will return the length of the string of the form element specified by
field in the ret parameter.
gcgiFieldLength should only be used for text data. If you are
trying to figure out how big a field is that is not text, such as an image or other file
use gcgiFieldSize() instead. Upon success,
GCGISUCCESS is returned. If the field is not present, then
GCGIFIELDNOTFOUND is returned.
gcgiResultType gcgiFieldLengthNext(char *field, int *ret)
This function is identical to gcgiFieldLength() except that if there are
multiple form elements of the same name, this function will return succeeding values if it is called
repeatedly. So, on the first call it returns the first instance of the form field, on the second
call, it would return the second instance, etc. Once all of the values have been iterated through,
the function will return GCGIFIELDNOTFOUND. The iteration can be started
over by calling gcgiResetMultipleField().
gcgiResultType gcgiFieldSizeNext(char *field, int *ret)
This function is identical to gcgiFieldLength() except that if there are
multiple form elements of the same name, this function will return succeeding values if it is called
repeatedly. So, on the first call it returns the first instance of the form field, on the second
call, it would return the second instance, etc. Once all of the values have been iterated through,
the function will return GCGIFIELDNOTFOUND. The iteration can be started
over by calling gcgiResetMultipleField().
gcgiResultType gcgiNumFormFields(int *ret)
This function will return the total number of fields submitted by the web browser in the
ret parameter. Upon success, GCGISUCCESS
is returned. If the field is not present, then GCGIFIELDNOTFOUND
is returned.
gcgiResultType gcgiNumFields(char *field, int *ret)
This function will return the number of fields with the name specified in field,
as submitted by the web browser. Upon success, GCGISUCCESS
is returned. If the field is not present, then GCGIFIELDNOTFOUND
is returned.
int gcgiFetchCheckbox(char *field, int *ret)
This function will return a 1 in the ret parameter if the form field,
specified by field is checked and 0 otherwise. Upon success,
GCGISUCCESS is returned. If the field is not present, then
GCGIFIELDNOTFOUND is returned.
gcgiResultType gcgiFetchMultipleCheckbox(char *field, char **data, int size, int **ret)
This function fills in the integer array, ret with either a 1 or 0 depending
if the corresponding checkbox, as specified by the web browser, was checked. data
must be an array of strings that contains the "value" parameter of the checkboxes as specified in the HTML form.
size must contain the number of elements in the data array.
If the HTML form contained the following elements:
<select type=checkbox name=colors value="red">
<select type=checkbox name=colors value="green">
<select type=checkbox name=colors value="blue">
gcgiResultType gcgiFetchMultipleString(char *field, char ***data)
This function will allocate an array of strings containing the values from multiple form elements
of the same name. It will also return the strings from a multiple select box. Upon success,
GCGISUCCESS is returned. If the field is not present, then
GCGIFIELDNOTFOUND is returned. If this function is called, then the
corresponding function, gcgiFreeMultipleString must be called to free the
memory allocated by it.
gcgiResultType gcgiFreeMultipleString(char **data)
This function frees the memory that is allocated by the gcgiFetchMultipleString()
funtion.
gcgiResultType gcgiFetchSelectIndex(char *field, char **data, int size, int *ret, int defaultVal)
This funtion returns the index of a selected string, radio button, or set of checkboxes. The
data parameter must contain an array of strings with the values of the radio buttons,
checkboxes or multiple-select boxes. If the field is not found, then the value in defaultVal
is returned in ret.
gcgiResultType gcgiResetMultipleField(char *field)
This function will reset GCGI's internal pointer to the first element of a field with multiple elements.
After a reset, the "Next" functions will return the first element for a particular field, eventually
iterating through them all.
Upon success, GCGISUCCESS is returned. If the field is not present, then
GCGIFIELDNOTFOUND is returned.
Cookie-Handling Functions
gcgiReturnType gcgiSendCookie(char *name, char *data, char *path, char *domain, char *expires, int secure, HTTPHeader header)
This function will send a Cookie to the client. It must be called after
gcgiSendContentType() is called. Various attributes of the cookie
can be set, but the only required parameters are name and
value. Every cookie must have a name and some data
that goes along with that name. The other parameters can be NULL. The
path specifies what path on the server the cookie should be submitted
for and the domain specifies to what domains the cookie should be sent.
The expires parameter specifies how long the cookie should be stored, if
this is omitted, the cookie will be deleted when the client browser is closed. The
secure parameter, if positive, specifies that the cookie should only be sent to secure
domains (HTTPS). Finally, if this is the last HTTP header to be sent, header
should be set to LAST, otherwise set it according to the next header you are
going to send. For full details of cookies, see the Netscape specification
included in the doc/ directory.
gcgiReturnType gcgiFetchCookies(char ***cookies)
This function returns a NULL-terminated array of strings, each string containing a cookie that was
sent from the client browser to your CGI program. If you call this function, you must call
gcgiFreeCookies() when you are done with them to free their memory.
gcgiReturnType gcgiParseCookie(char *cookie, char **name, char **data)
This function will parse a single cookie, returning the name of the cookie and
the data associated with it. Generally, you will want to fetch all cookies
using the gcgiFetchCookies() function, and then iterate through that list calling this
function.
gcgiReturnType gcgiFreeCookies(char **cookies)
This function frees the memory associated with an array of cookies that is created with the
gcgiFetchCookies() function.
gcgiReturnType gcgiSendEncryptedCookie(char *name, char *value, char *path, char *domain, char *expires, int secure, unsigned char *key, HTTPHeader header)
Identical to gcgiSendCookie() except you must pass in a key
and the cookie will be encrypted. You must build with OpenSSL to use this function.
gcgiReturnType gcgiParseEncryptedCookie(char *cookie, unsigned char *key, char **name, char **value)
Identical to gcgiParseCookie() except you must pass in a key
so that the cookie can be decrypted. You must build with OpenSSL to use this function.
gcgiReturnType gcgiGenerateKey(unsigned char **key)
This function will generate a key to use for encrypting and decrypting. You must build with OpenSSL
to use this function.
gcgiReturnType gcgiWriteKeyToFile(unsigned char *key, char *path)
This function will write a key to an external file. While GCGI can generate and use keys for encrypting
and decrypting, the calling program has the responsibility to store that key. This function can help with
that task by writing it properly to a file. You must build with OpenSSL to use this function.
gcgiReturnType gcgiReadKeyFromFile(char *path, unsigned char **key)
This function will read a key to an external file. While GCGI can generate and use keys for encrypting
and decrypting, the calling program has the responsibility to store that key. This function can help with
that task by reading it properly from a file. You must build with OpenSSL to use this function.
HTTP Header Functions
gcgiResultType gcgiSendContentType(char *mimeType, char *name, char *charset, HTTPHeader header)
This function will send a Content-Type header back to the client browser.
This function must be called before any other HTTP header functions. mimeType
should be a valid MIME string, such as text/html or image/png.
name and charset are optional. If this is the only HTTP
header you are sending then header should be LAST, otherwise
set it according to the next header you are going to send.
gcgiResultType gcgiSendContentDisp(MimeDisposition disp, char *filename, HTTPHeader header)
This function will send a Content-Disposition header. You must call the
gcgiSendContentType() first. disp should be either
inlined or attachment and filename
should be a string that you want the client browser to use to save the file as. If this is the last HTTP
header you are sending then header should be LAST, otherwise
set it according to the next header you are going to send.See the
fileupload example on ways to use this.
gcgiReturnType gcgiSendContentLength(int length, HTTPHeader header)
This function will send a Content-Length header. This allows you to specify
how much data you are sending (specified in octets) to the client browser. Useful when dynamically
generating things like images.
gcgiResultType gcgiSendCacheControl(char *cache, HTTPHeader header)
This function allows you to send various cache control directives to the client browser and proxy
machines in between the CGI program and the client browser. See RFC2616 for details on this header
(it is included in the doc/ directory). If this is the last HTTP header you are
sending then header should be LAST, otherwise
set it according to the next header you are going to send.
gcgiResultType gcgiSendLocation(char *redirectURL)
This function will tell the client browser to redirect itself to the URL provided in
redirectURL. This function must not be called with any other HTTP functions.
gcgiResultType gcgiSendStatus(int status, char *message)
This function will send the client browser an HTTP status number and a message to go along with that
number. See RFC2616 for details on this header (it is included in the
doc/ directory). This function must not be called with any other HTTP functions.
Debugging Functions
gcgiResultType gcgiDebug(char *envpath, char *querypath)
This function will place GCGI into debug mode. It will load the environment variables from the
filepath contained in envpath, and will load query data from
querypath. The environment variables can be captured to a file by calling
gcgiSaveEnvVariables(), the query data file is only needed if you are
debugging POST queries and you must create it your self. In the future, GCGI wlil be able to generate it,
until then you can use the gcgiGetInput program included in
the examples/ directory to capture it.
gcgiResultType gcgiLoadEnvVariables(char *path)
This function will load all of the necessary CGI environment variables from a file to facilitate
debugging. Using this factility, CGI programs can be run through a debugger, or from the command line.
gcgiResultType gcgiSaveEnvVariables(char *path)
This function will capture a CGI environment to a file for later use with
gcgiLoadEnvVariables().
gcgiResultType printQuery(FILE *stream)
This function will dump a textual representation of the GCGI structures to a file stream.
Their are several examples included in the GCGI tarball that do the following:
gcgiFormTest -- An example of a vanilla CGI program that fetches data from an HTML form. Use this program with the formexample.html file.
gcgiFileUploadTest -- An example of how to upload files with GCGI. Use this program with the fileupload.html file.
gcgiCookieTest -- An example of how to use regular and encrypted cookies with GCGI. Use this program with the cookietest.html file.
gcgiGetInput -- A small utility program that will capture the input to a CGI program. This is useful when debugging with GCGI. Use this program to capture the incoming POST data and use it along with the gcgiDebug() method in GCGI to run a program in a debugger or from the command line. It was used to capture the POST data files included in the examples directory.
Debuging:
#include <stdlib.h> #include <stdio.h> #include "gcgi.h" int main (int argc, char *argv[], char *envp[]) { if (initCgi() < 0) return -1; gcgiSaveEnvVariables("./urlencodedenv"); freeCgi(); return 0; }
Next you need to capture the CGI query string. The easiest way to do this is to set your HTML form to use a GET query. Then, after submitting the form, you can copy the query string directly from the address input in the web browser or from the environment variables file that is created (use the QUERY_STRING variable).
If you have a POST query that you want to capture, use the utility program, gcgiGetInput included in the examples/ directory. Set your HTML form to submit its data to this program, which will then output it, unmodified, to a file.
Here is an example of the environment variables file that would be created with the GET string added to the QUERY_STRING variable:
CONTENT_LENGTH= CONTENT_TYPE=application/x-www-form-urlencoded GATEWAY_INTERFACE=CGI/1.1 QUERY_STRING=string=some+text&integer=432&double=12.3985 REMOTE_ADDR=192.168.0.2 REQUEST_METHOD=POST SCRIPT_NAME=/cgi-bin/gcgitest SERVER_NAME=topeka.shingletowngap.org SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.1 SERVER_SOFTWARE=Apache/1.3.9 (Unix) (SuSE/Linux) mod_perl/1.21
#include <stdlib.h> #include <stdio.h> #include "gcgi.h" int main (int argc, char *argv[], char *envp[]) { gcgiDebug("./urlencodedenv", "./urlencodedquery"); if (initCgi() < 0) return -1; /* Insert useful code here */ freeCgi(); return 0; }
GCGI has been implemented from scratch, cleanroom-style. However, the API attempts to be close to Thomas Boutell's CGIC where it makes sense. Unfortunately, CGIC does not provide RFC2388 functionality and CGIC's non-free license prevented extensions to the existing library. So, GCGI was written to fill this gap.
Who:GCGI was written by Julian Catchen.