"Fossies" - the Fresh Open Source Software Archive

Member "libgcgi.a-0.9.5/doc/gcgi.html" (22 Jun 2002, 41811 Bytes) of package /linux/www/old/gcgi-0.9.5.tar.gz:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the gcgi-0.9.5.tar.gz project site itself.

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:

Features:

Installation:

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 gcgiFieldSize(char *field, int *ret)
This function will return the amount of space needed for the form element specified by field in the ret parameter. If the data you are receiving is binary, such as an image file, this function will return the size of the image as it is stored by GCGI. Upon success, GCGISUCCESS is returned. If the field is not present, then GCGIFIELDNOTFOUND is returned.

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">

Then data would contain "red", "green" and "blue", ret would be a 3 element integer array and field would contain "colors".

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.

Examples:

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:

  1. You first need to capture a running CGI environment to a file. To do this, use the gcgiSaveEnvVariables(char *path) function. Either place it into the program you are trying to debug, or create a small program that you invoke form the HTML form and use it to capture the environment. Something like this will do:

    #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; }

  2. 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

  3. Last, add a call to your program before the initCgi() call to gcgiDebug(char *envpath, char *querypath) specifying the two files created above. If you are testing a GET query using the QUERY_STRING environment varible, then the second file is not necessary and you can just passin a blank string. However, to test POST queries, or RFC2388 queries, you need to specify the second file. GCGI will now read its input from the specified files rather than from the webserver.
  4. Now, you should be able to run your program through a debugger or directly from the command line.

    #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; }

History:

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.

Julian M Catchen
Last modified: Sat Jun 15 19:14:05 MST 2002