JemTek CGI v1.03

Copyright © 1996 JemTek
Written by Jerome Munchenberg
Email to jerome@jemtek.com.au


Contents

Introduction

Programmer's Guide

Library Reference

Miscellaneous


Introduction

Welcome!

JemTek CGI is a C library designed to simplify the creation of dynamic World Wide Web (WWW) applications. Dynamic applications are possible via the Common Gateway Interface (CGI) which provides an interface for running applications under an information server in a platform-independent manner. JemTek CGI is designed to be compatible with any CGI enabled HTTP server.

If the above paragraph reads like gobbledegook, please refer yourself to the reference section for relevant reading.

JemTek CGI performs the following:

The JemTek CGI library is small, fast and user-friendly. It aims to provide a simple interface for the CGI programmer with strong functionality and succinct documentation. I believe it is a combination of all these factors that make it an excellent choice for CGI application development.

I appreciate user feedback. Problems with the software or errors in the documentation? Let me know! Every attempt will be made to address enquiries.

Direct email to Jerome Munchenberg at jerome@jemtek.com.au


History

Future Enhancements

Version 1.03 [11th February 1997]

Version 1.02 [6th December 1996]

Version 1.01 [29th September 1996]

Version 1.0 [18th March 1996]


Acknowledgements

Thanks go to:


License

By obtaining, installing, copying or using the software and associated documentation (the 'package') you agree that you have read, understood and are bound by the terms of the license. Please use the
order form to purchase your license and keep me eating for a while longer!

Direct enquires to Jerome Munchenberg at jerome@jemtek.com.au


Download

The source code and documentation for the JemTek CGI library is available in archive format. Select one of the following options:

Installation

Follow the instructions below to extract the archive.

TAR Archive

The tar archive format is popular on UNIX machines where the tar utility is usually installed by default. The following command will extract the archive:
  tar xvf jmtk_cgi.tar
  

ZIP Archive

The zip archive format is popular on DOS machines, however you must have a zip/unzip utility to extract these files. The following command will extract the archive:
  unzip -d jmtk_cgi.zip
  

File List

Extracting the archive will create the sub-directory jmtk_cgi which will contain the following files:
  cgi.h         - JemTek CGI library header file
  cgi.c         - JemTek CGI library source code
  cgi.htm       - Users manual in html format
  makefile      - Makefile to build the library and sample application.
  test_cgi.c    - Sample CGI application source code
  test_cgi.htm  - Sample HTML document
  

Building

Included in the archive is a simple makefile which builds both the JemTek CGI library and the sample CGI application. Type:
  cd jmtk_cgi
  make
  
Once the make is complete four new files should exist; two object files cgi.o and test_cgi.o which may be removed, the JemTek CGI library, libcgi.a, and the sample CGI application binary, test_cgi.

Sample Code

The JemTek CGI package includes a sample CGI application, test_cgi.c which accepts requests submitted by the HTML document test_cgi.htm.

The HTML document demonstrates the use of all the available HTML query submission methods via a number of simple examples. In response to a query submission, the CGI application returns a HTML page which shows the submitted data parsed into pairs and the values of CGI-specific environment variables. The operation of this application is so general it can be used with any HTML document submitting a request, yet the output is extensive enough to be useful as a simple debugging aid.

To try the sample application in your own environment:


Writing Applications

For the purpose of instruction it is assumed you have prepared a HTML document that submits requests to a CGI program via one of either: Begin your code by including the JemTek CGI library header file:
  #include "cgi.h"
  
The JemTek CGI library requires you to declare the global variable cgiDebug of type character pointer. This variable makes possible the debugging of CGI applications. See the section on debugging applications for further information but for standard applications it is enough just to simply declare the variable:
  #include "cgi.h"

  char *cgiDebug;
  
The JemTek CGI library uses the main() function to do important initialisation tasks before passing control to your application. Instead of using the main() function, the body of your application should be placed in the cgiMain() function. Attempting to use your own main() function will result in linking problems.
  #include "cgi.h"

  char *cgiDebug;

  int cgiMain()
  {
    ... your application here ...
  }
  
Within cgiMain() you must indicate to the browser the MIME type of the document your application will return. This is accomplished by the various cgiHeader.. functions, one of which must be invoked. The most common response is another HTML document:
  #include "cgi.h"

  char *cgiDebug;

  int cgiMain()
  {
    cgiHeaderContent("text/html");

    ... your application here ...
  }
  
If your application is returning a HTML document, you can use the convenient HTML wrapper functions cgiHtmlHead() and cgiHtmlTail():
  #include "cgi.h"

  char *cgiDebug;

  int cgiMain()
  {
    cgiHeaderContent("text/html");

    cgiHtmlHead("_your_app_title_");

    ... your application here ...

    cgiHtmlTail();
  }
  
Without the wrappers the equivalent code would be:
  #include "cgi.h"

  char *cgiDebug;

  int cgiMain()
  {
    cgiHeaderContent("text/html");

    cgiPrintf("<HTML>");
    cgiPrintf("<HEAD>");
    cgiPrintf("<TITLE>_your_app_title_</TITLE>");
    cgiPrintf("</HEAD>");
    cgiPrintf("<BODY>");

    ... your application here ...

    cgiPrintf("</BODY>");
    cgiPrintf("</HTML>");

    fflush(stdout);
  }
  
You may have noticed the use of cgiPrintf in the above code snippet. This function should be used instead of printf as it is specifically written for use in CGI applications.

A request submitted by either the GET or POST method sends a stream of var=val pairs. The ISINDEX method only submits vals and in this instance the library automatically creates a var=val pair by setting var to isindex.

var=val pairs can be displayed with a call to cgiDisplayPairs(). A number of functions are available to retrieve and query these pairs:

For example, say we have an ISINDEX request. The following code lets us know how many keywords the user submitted:
  int val;
  ...
  val = cgiFormCntVar("isindex");
  
As another example, say we have a multiple select listbox with the name box. The following code retrieves each value selected by the user:
  char **vals;
  int    val, cnt;
  ...
  val = cgiFormGetValMulti("box", &vals);

  if (val==0)
    cgiPrintf("The user selected nothing from the multi select listbox!");
  else
  {
    cgiPrintf("The following was selected from the multi select listbox!");
    for (cnt=0; cnt<val; cnt++)
      cgiPrintf("%s", vals[cnt]);
  }
  
There are many other available library functions to aid the creation of a CGI application. For a list of what functionality is available, please browse the library reference.

Once your code is complete and you are ready to build an executable, compile your code by linking to the JemTek CGI library:

  $(CC) -Ljmtk_cgi -lcgi -o _your_exe_ _your_src_
  
Depending on how your administrator has configured the server environment your application should have the filename extension .cgi and/or be placed in the appropriate CGI script directory, usually named cgi-bin. Furthermore, ensure the URL in your form correctly indicates the location of your CGI application.

All things being equal, submitting a request via your HTML page should result in your CGI application responding with a new page. If the response was not quite what you expected please review the sections on debugging and problem solving.


Debugging Applications

A WEB server creates a special environment for executing CGI applications which involves the setting of environment variables, command-line arguments and the standard input file. Recreating this environment is difficult and painful and makes debugging almost impossible.

JemTek CGI provides a method of capturing an instance of this environment to file. With the environment thus preserved, a CGI application can be executed any number of times from the command-line or debugger as though it had been launched by the WEB server itself.

The following steps capture and replay an environment:

The JemTek CGI library requires you to declare the variable cgiDebug as a global character pointer. For normal operation this variable should be left uninitialised.

  #include "cgi.h"

  char *cgiDebug;

  int cgiMain()
  {
    ... your application here ...
  }
  
An environment can be captured by initialising this variable to the string SAVE=_env_file_ where _env_file_ is the file in which the environment is to be saved. Make sure the file path is absolute and writable by the WEB server.
  #include "cgi.h"

  char *cgiDebug = "SAVE=_env_file_";

  int cgiMain()
  {
    ... your application here ...
  }
  
Build the application and place the binary in the appropriate CGI directory. Open your HTML document in a browser and submit a request. You should receive a response stating whether or not the environment was successfully captured.

Once the environment has been captured, modify the cgiDebug string by replacing SAVE with LOAD. Rebuild your application.

  #include "cgi.h"

  char *cgiDebug = "LOAD=_env_file_";

  int cgiMain()
  {
    ... your application here ...
  }
  
You can now execute your application from the command-line or debugger as though launched by the WEB server!


Problem Solving

If after reading the above hints your problem still exists, please attempt to resolve them with your WEB server administrator before mailing a query or bug report. Please see the section on support for more information.


Index of functions

void cgiDisplayEnv ();
void cgiDisplayPairs ();
char* cgiEncodeSys (char *data);
char* cgiEncodeUrl (char *data);
int cgiFormCmpVal (char *var, char *val);
int cgiFormCmpValMulti (char *var, char len, char **vals);
int cgiFormCntVar (char *var);
char* cgiFormGetVal (char *var);
int cgiFormGetValMulti (char *var, char ***vals);
cgiHeader..
int cgiHeaderContent (char *mimeType);
int cgiHeaderLocation (char *redirectUrl);
int cgiHeaderStatus (int statusCode, char *statusReason, char *statusMesg);
int cgiHeaderNonParse (int statusCode, char *statusMesg, char *mimeType);
int cgiHtmlHead (char *title);
int cgiHtmlTail ();
int cgiImageOk ();
int cgiLoad (char *file);
extern int cgiMain ();
int cgiPrintf (char *fmt, ...);


Description of functions

cgiDisplayEnv

Syntax void cgiDisplayEnv();
Function Display the cgiEnv structure in HTML format.
Remarks A number of environment variables are set by the WEB server before launching a CGI program. These variables are placed in the cgiEnv structure during initialisation. This function displays the contents if the cgiEnv structure in HTML format.
Return None.
See Also cgiDisplayPairs()

cgiDisplayPairs

Syntax void cgiDisplayPairs();
Function Display the form data pairs in HTML format.
Remarks CGI data is parsed into var=val pairs during initialisation. This function displays these pairs in HTML format. Square brackets are placed around the value field to help indicate any white spaces.
Return None.
See Also cgiDisplayEnv()

cgiEncodeSys

Syntax char *cgiEncodeSys(char *data);
Function Escape shell metacharacters in a string.
Remarks This function is useful as a security precaution if user input is allowed in calls to low-level functions such as system or popen within a CGI program. All Bourne and C shell meta-characters are escaped.
Return Success: A pointer to the encoded string.
Failure: NULL.

cgiEncodeUrl

Syntax char *cgiEncodeUrl(char *data);
Function URL-encode a string.
Remarks Converts space characters to plus and non alpha-numeric characters to their hexadecimal equivalent. The resultant string can be used within a URL.
Return Success: A pointer to the encoded string.
Failure: NULL.

cgiFormCmpVal

Syntax int cgiFormCmpVal(char *var, char *val);
Function Compares the value of a variable with another value.
Remarks Find each occurrence of the variable, var and compare it's value with the supplied value, val. Function is successful if an exact match is made.
Return Success: 1.
Failure: 0.
See Also cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti()

cgiFormCmpValMulti

Syntax int cgiFormCmpValMulti(char *var, char len, char **vals);
Function Compares the value of a variable with an array of values.
Remarks Find each occurrence of the variable, var and compare it's value with the supplied array of values, vals, having len entries. Function is successful if an exact match is made.
Return Success: 1.
Failure: 0.
See Also cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti()

cgiFormCntVar

Syntax int cgiFormCntVar(char *var);
Function Test for a variable.
Remarks Searches for all instances of the variable, var. Function is successful if an exact match is found.
Return Success: The number of instances of var.
Failure: 0.
See Also cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti()

cgiFormGetVal

Syntax char *cgiFormGetVal(char *var);
Function Return the value of the given variable.
Remarks Searches for the first instance of the variable, var, and if successful, return it's associated value.
Return Success: A pointer to a string.
Failure: NULL.
See Also cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti()

cgiFormGetValMulti

Syntax int cgiFormGetValMulti(char *var, char ***vals);
Function Return multiple values of the given variable.
Remarks Searches for all instances of the variable, var and if successful, places all it's associated values in vals, returning the number of matches.
Return Success: The number of strings placed into vals.
Failure: 0, with vals set to NULL.
See Also cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti()

cgiHeader..

Syntax int cgiHeaderContent(char *mimeType);
int cgiHeaderLocation(char *redirectUrl);
int cgiHeaderStatus (int statusCode, char *statusReason, char *statusMesg);
int cgiHeaderNonParse (int statusCode, char *statusMesg, char *mimeType);
Function Identify the type of document the CGI program will produce.
Remarks A cgiHeader.. function must be invoked before outputting any data. An attempt to invoke a cgiHeader.. function a second time will fail. As a further measure, calls to cgiPrintf will fail until a cgiHeader.. function is invoked. If a cgiHeader.. function is not invoked, the CGI program responds with an appropriate error.
Return Success: 1.
Failure: 0.
See Also cgiHeaderContent(), cgiHeaderLocation(), cgiHeaderStatus(), cgiHeaderNonParse()

cgiHeaderContent

Syntax int cgiHeaderContent(char *mimeType);
Function Indicate the MIME type of the document.
Remarks Usually a CGI program responds with a document, in which case it must be initially identified as a MIME type, typically "text/html". Common MIME types are "text/html", "text/plain", "image/gif", "audio/basic" and "video/mpeg".
Return Success: 1.
Failure: 0.
See Also cgiHeader.., cgiHeaderLocation(), cgiHeaderStatus(), cgiHeaderNonParse()

cgiHeaderLocation

Syntax int cgiHeaderLocation(char *redirectUrl);
Function Redirect the browser to a new resource.
Remarks Specifies that the CGI program is returning a reference to the document, redirectUrl, rather than producing a document. In this instance, no further output is required.
Return Success: 1.
Failure: 0.
See Also cgiHeader.., cgiHeaderContent(), cgiHeaderStatus(), cgiHeaderNonParse()

cgiHeaderStatus

Syntax int cgiHeaderStatus (int statusCode, char *statusReason, char *statusMesg);
Function Return an error status.
Remarks Specifies that the CGI program is returning with an error rather than producing a document. The statusCode (a 3-digit number) and statusReason (a string briefly identifying the error) define the HTTP status line (as specified in the protocol) to send to the client. The statusMesg is a user-defined string further clarifying the error. The output looks something like this:
      Content-type: text/html
      Status: 500 Internal Server Error

      <H2>500 Internal Server Error</H2>
      <H3>Sorry, could not allocate memory or some such</H3>
      
Return Success: 1.
Failure: 0.
See Also cgiHeader.., cgiHeaderContent(), cgiHeaderLocation(), cgiHeaderNonParse()

cgiHeaderNonParse

Syntax int cgiHeaderNonParse (int statusCode, char *statusMesg, char *mimeType);
Function Indicate that the document is to be sent directly to the client with minimal buffering.
Remarks Usually the output of a CGI program is sent to the server and then on to the client. In this instance the server is by-passed. Server documentation specifies that non-parse documents should be named with the prefix nph-. The statusCode (a 3-digit number) and statusReason (a string briefly identifying the error) define the HTTP status line (as specified in the protocol) to send to the client.
Return Success: 1.
Failure: 0.
See Also cgiHeader.., cgiHeaderContent(), cgiHeaderLocation(), cgiHeaderStatus()

cgiHtmlHead

Syntax int cgiHtmlHead(char *title);
Function Initialises a HTML document.
Remarks Essentially a wrapper for the initialisation of a HTML document, the function encapsulates the following calls:
      cgiPrintf("<HTML>");
      cgiPrintf("<HEAD>");
      cgiPrintf("<TITLE>title</TITLE>");
      cgiPrintf("</HEAD>");
      cgiPrintf("<BODY>");
      
This function will fail until a cgiHeader..() function is invoked.
Return Success: 1.
Failure: 0.
See Also cgiHtmlTail()

cgiHtmlTail

Syntax int cgiHtmlTail();
Function Finalises a HTML document.
Remarks Essentially a wrapper for the finalisation of a HTML document, the function encapsulates the following:
      cgiPrintf("</BODY>");
      cgiPrintf("</HTML>");
      
This function will fail until cgiHtmlHead() has been invoked.
Return Success: 1.
Failure: 0.
See Also cgiHtmlHead()

cgiImageOk

Syntax int cgiImageOk();
Function Determines the browser's ability to view images.
Remarks Examines the cgiEnv.httpAccept environment variable for an instance of the MIME type image/....
Return Success: 1.
Failure: 0.
See Also cgiEnv

cgiLoad

Syntax int cgiLoad(char *file);
Function Copy an external file into the current document.
Remarks Opens a file and copies its contents to stdout. Useful for displaying existing HTML or text documents.
Return Success: 1.
Failure: 0.

cgiMain

Syntax extern int cgiMain();
Function Entry point for the CGI application.
Remarks The JemTek CGI library uses the main() function to do important initialisation tasks before passing control to a CGI application. The CGI application code should instead be written within the cgiMain function.

Initialisation tasks undertaken by the JemTek CGI library involve saving or loading debug environments, determining the request method, parsing data into var=val pairs, and setting values in the cgiEnv structure. An ISINDEX method does not submit var=val pairs, only vals. The library creates a var=val by setting var to isindex.

Return Success: 1.
Failure: 0.

cgiPrintf

Syntax int cgiPrintf(char *fmt, ...);
Function Print variable argument strings to stdout.
Remarks This function is identical to the standard printf but with added functionality specifically suited to CGI applications.
  • A line feed is attached to the end of the output.
  • Output is flushed. This ensures a correct output sequence, and provides prompt response at the browser.
  • Calls to cgiPrintf will fail if a cgiHeader.. function has not previously been invoked.
Return Success: 1.
Failure: 0.

Index of global variables

  extern char *cgiDebug;
  
  struct {
    char *authType;
    int   contentLength;
    char *contentType;
    char *gatewayInterface;
    char *httpAccept;
    char *httpHost;
    char *httpReferer;
    char *httpUserAgent;
    char *pathInfo;
    char *pathTranslated;
    char *queryString;
    char *remoteAddr;
    char *remoteHost;
    char *remoteIdent;
    char *remoteUser;
    char *requestMethod;
    char *scriptName;
    char *serverName;
    char *serverPort;
    char *serverProtocol;
    char *serverSoftware;
  } cgiEnv;
  

Description of global variables

cgiDebug

Syntax extern char *cgiDebug;
Remarks This variable must be declared globally within your CGI application and permits the debugging of the application. For normal operation this variable should be left uninitialised. However, if initialised to "SAVE=_env_file", the application will save the CGI environment to the specified file. Initialised to "LOAD=_env_file_" the application will reload a saved environment. For more information please read the section on debugging applications.

cgiEnv

Syntax struct {
char *authType;
int contentLength;
char *contentType;
char *gatewayInterface;
char *httpAccept;
char *httpHost;
char *httpReferer;
char *httpUserAgent;
char *pathInfo;
char *pathTranslated;
char *queryString;
char *remoteAddr;
char *remoteHost;
char *remoteIdent;
char *remoteUser;
char *requestMethod;
char *scriptName;
char *serverName;
char *serverPort;
char *serverProtocol;
char *serverSoftware;
} cgiEnv;
Remarks The programmer is provided with predefined global variables of CGI- specific environment variables. These should be used instead of calls to getenv. The variables are never null, but may point to an empty string. Please note that the http... variables are not always set by browsers. The fields are as follows:
authType The type of authentication used, if any. If authentication is required this is normally set to basic.
contentLength The size in bytes of the query data received.
contentType The MIME type of the information sent by a user. Should be set to application/x-www-form-urlencoded for the POST method.
gatewayInterface The name of the gateway interface. ie. CGI/1.1
httpAccept A comma delimited string of MIME types acceptable to the browser. ie. image/gif, image/x-xbitmap, image/jpeg, */*.
httpHost The URL of the browser host.
httpReferer The URL of the request.
httpUserAgent The name of the client browser. ie. Mozilla/2.0.
pathInfo Set to any additional path information in the URL of the request beyond the name of CGI program itself.
pathTranslated A server filesystem path corresponding to an absolute URL containing pathInfo.
queryString A URL encoded string containing information submitted by a user via the ISINDEX or GET methods.
remoteAddr The IP address of the browser.
remoteHost The domain name of the browser.
remoteIdent The user-volunteered user identifier. This variable is not appropriate for authentication.
remoteUser If user authentication is on (authType=basic) then this will be the username with which the client was authenticated.
requestMethod The method with which the request was made. Usually set to GET (for both ISINDEX and GET methods) or POST.
scriptName A URL path that identifies the CGI script.
serverName Either the domain name or IP address of the server.
serverPort The server port on which the request was received.
serverProtocol The information protocol of the request. ie. HTTP/1.0.
serverSoftware The name of the server software. ie. NCSA/1.5.


References

World Wide Web

Yahoo WWW Reference
World Wide Web FAQ WWW Security FAQ

Hypertext Transfer Protocol

Yahoo HTTP Reference
Hypertext Transfer Protocol Working Group Hypertext Transfer Protocol - HTTP/1.1 NSCA HTTPd Documentation

Hypertext Markup Language

Yahoo HTML Reference
Usenet - comp.infosystems.www.authoring.html Hypertext Markup Language Working Group Sandia National Labratories HTML Reference Manual

Common Gateway Interface

Yahoo CGI Reference
Usenet - comp.infosystems.www.authoring.cgi The CGI FAQ NSCA CGI Documentation JemTek CGI Applications

Miscellaneous

MIME Media Types