cgic: an ANSI C library for CGI Programming By Thomas Boutell The LATEST documentation is available here. Check often for new releases. Table of Contents * Credits and license terms * How to get support * What's new in version 1.05? * What's new in version 1.04? * What's new in version 1.03? * What is cgic? * Obtaining cgic * Building and testing cgic: a sample application * What to do if it won't compile * How to write a cgic application * How can I generate images from my cgic application? * CGI debugging features: using capture * cgic function reference * cgic variable reference * cgic result code reference * cgic quick index Credits and License Terms cgic can be used free of charge, provided that a credit notice is provided online. Alternatively, a nonexclusive Commercial License can be purchased, which grants the right to use cgic without a public credit notice. Please see the file license.txt for the details of the Basic License and Commercial License, including ordering information for the Commercial License. How to Get Support Anyone can mail questions about the gd and cgic libraries to boutell@boutell.com. However, I receive a very large volume of email on many subjects, and while I do my best to respond to all queries this can take some time. Sometimes the response must take the form of an eventual new release or an addition to a FAQ or other document, as opposed to an individual response. However, priority support is available. Priority support customers receive a special support email address from which a personal response within 24 hours (on working days) is provided. Of course, purchasing priority support also encourages further enhancement of cgic, gd and related free boutell.com software. Priority support can be purchased at the rate of $50 per month, with up to 12 distinct queries per month (reasonable back-and-forth exchanges to resolve a single query are not charged against this limit). After the twelfth query, each additional query costs $5. Preparations to handle support purchases through First Virtual are being made; support may also be paid for by check or money order. Alternatively, priority support may be purchased à la carte at a rate of $5 per query. To purchase priority support, send mail to support-request@boutell.com indicating the time period (or number of queries) for which you wish to purchase support and the address to which boutell.com should send an invoice. Invoices may be sent by email or postal mail, at your option, although boutell.com supports resource conservation efforts and prefers to invoice via email when possible. Once you receive the invoice, boutell.com will expect payment within 30 days. You will begin to receive priority support as soon as you declare your intention to purchase said support. Currently, priority support is intended only to resolve specific difficulties with the gd and cgic libraries. boutell.com priority support is not a budget consulting service. Other inquiries regarding boutell.com software, documentation and the like should be sent to boutell@boutell.com. What's new in version 1.05? Non-exclusive commercial license fee reduced to $200. What's new in version 1.04? For consistency with other packages, the standard Makefile now produces a true library for cgic (libcgic.a). What's new in version 1.03? Version 1.03 sends line feeds only (ascii 10) to end Content-type:, Status:, and other HTTP protocol output lines, instead of CR/LF sequences. The standard specifies CR/LF. Unfortunately, too many servers reject CR/LF to make implementation of that standard practical. No server tested ever rejects LF alone in this context. What's new in version 1.02? Version 1.02 corrects bugs in previous versions: * cgiFormDoubleBounded specified its arguments in the wrong order, with surprising results. This bug has been corrected. * Many small changes have been made to increase compatibility. cgic now compiles with no warnings under the compilers available at boutell.com. What's new in version 1.01? Version 1.01 adds no major functionality but corrects significant bugs and incompatibilities: * cgiFormInteger, cgiFormIntegerBounded, cgiFormDouble and cgiFormDoubleBounded now accept negative numbers properly. They also accept positive numbers with an explicit + sign. * Hex values containing the digit 9 are now properly decoded. * cgiFormString now represents each newline as a single line feed (ascii 10 decimal) as described in the documentation, not a carriage return (ascii 13 decimal) as in version 1.0. The latter approach pleased no one. * cgiFormString and cgiFormStringNoNewlines no longer erroneously return cgiFormEmpty in place of cgiFormSuccess. * The main() function of cgic now flushes standard output and sleeps for one second before exiting in order to inhibit problems with the completion of I/O on some platforms. This was not a cgic bug per se, but has been reported as a common problem with CGI when used with the CERN server. This change should improve compatibility. * The single selection example in the testform.html example now works properly. This was an error in the form itself, not cgic. * cgiRemoteUser and cgiRemoteIdent are now documented accurately. They were reversed earlier. What is cgic? cgic is an ANSI C-language library for the creation of CGI-based World Wide Web applications. For basic information about the CGI standard, see the CGI documentation at NCSA. cgic performs the following tasks: * Parses form data, correcting for defective and/or inconsistent browsers * Transparently accepts both GET and POST form data * Handles line breaks in form fields in a consistent manner * Provides string, integer, floating-point, and single- and multiple-choice functions to retrieve form data * Provides bounds checking for numeric fields * Loads CGI environment variables into C strings which are always non-null * Provides a way to capture CGI situations for replay in a debugging environment * Provides a somewhat safer form of the system() function cgic should be compatible with any CGI-compliant server environment. Obtaining cgic cgic is distributed via the web in two forms: as a Windows-compatible .ZIP file, and as a compressed tar file. Most users of Windows and related operating systems have access to 'unzip' or 'pkunzip'. All Unix systems come with 'uncompress' and 'tar' as standard equipment. Versions of these programs for other operating systems are widely available if you do not already have them. Important: to use cgic, you will need an ANSI-standard C compiler. The Sun cc distributed with SunOS 4.1.3 is not ANSI-standard. Unix users may wish to obtain gcc, which is free and widely available, or purchase Sun's development package, which also includes a proper compiler. Users of Windows-related operating systems should not have ANSI C-related problems as all of the popular compilers follow the ANSI standard. Note for Windows Programmers: cgic should work in a 16-bit environment but is not designed to cater to such an environment. Form fields which require more than 64K individually will not work as expected unless the huge memory model is used. Using a 32-bit compiler is strongly recommended. Your web browser should inquire whether to save the file to disk when you select one of the links below. Under Unix and compatible operating systems, save it, then issue the following commands to unpack it: uncompress cgic105.tar.Z tar -xf cgic105.tar This should produce the subdirectory 'cgic105', which will contain the complete cgic distribution for version 1.05, including a copy of this documentation in the file cgic.html. Under Windows and compatible operating systems, save it, open a DOS window, and issue the following commands to unpack it: pkunzip /d cgic105.zip This command also produces the subdirectory 'cgic105', which will contain the complete cgic distribution for version 1.05, including a copy of this documentation in the file CGIC.HTM. cgic is available via the web from www.boutell.com: * Obtain cgic: compressed tar file * Obtain cgic: .ZIP file Building cgic: a sample application The sample application 'cgictest.c' is provided as part of the cgic distribution. This CGI program accepts input submitted by the form cgictest.html. On a Unix system, you can build cgictest simply by typing 'make cgictest'. cgic.c and cgictest.c will be compiled and linked together to produce the cgictest application. Under non-Unix operating systems, you will need to create and compile an appropriate project containing the files cgic.c and cgictest.c. IMPORTANT: after compiling cgictest, you will need to place it in a location on your server system which is designated by your server administrator as an appropriate location for CGI scripts. Also, the URL of the action of the sample form in testform.html must be changed to correctly indicate the location of cgictest on your web server. The right locations for CGI programs vary greatly from one server to another. Resolving this issue is between you, your web server administrator, and your web server documentation. Before submitting a bug report for cgic, make certain that the CGI example programs which came with your server do work for you. Otherwise it is very likely that you have a server configuration problem. Once you have moved cgictest to an appropriate cgi directory and edited form.html to properly refer to its location, use the web browser of your choice to access form.html. Fill out the various fields in any manner you wish, then select the SUBMIT button. If all goes well, cgictest will respond with a page which indicates the various settings you submitted. If not, please see the second paragraph above. What to do if it won't compile * Make sure you are using an ANSI C or C++ compiler. * If your compiler can't find the #include file unistd.h, define the preprocessor macro NO_UNISTD and recompile. * If your compiler can't find the function system(), define the preprocessor macro NO_SYSTEM and recompile. * If your compiler can't find the function sleep(), remove the call to that function from the main() function of cgic.c and recompile. If none of the above proves effective, please see the section regarding support. How to write a cgic application Note: All cgic applications must be linked to the cgic.c module itself. How to do this depends on your operating system; under Unix, just use the provided Makefile as an example. Since all CGI applications must perform certain initial tasks, such as parsing form data and examining environment variables, the cgic library provides its own main() function. When you write applications that use cgic, you will begin your own programs by writing a cgiMain() function, which cgic will invoke when the initial cgi work has been successfully completed. Your program must also be sure to #include the file cgic.h. Important: if you write your own main() function, your program will not link properly. Your own code should begin with cgiMain(). The library provides main() for you. Consider the cgiMain function of cgictest.c: int cgiMain() { #if DEBUG /* Load a saved CGI scenario if we're debugging */ cgiReadEnvironment("/path/to/capcgi.dat"); #endif /* Important: we must indicate the type of document */ cgiHeaderContentType("text/html"); /* Now invoke other functions to handle each part of the form */ fprintf(cgiOut, "\n"); fprintf(cgiOut, "cgic test\n"): fprintf(cgiOut, "

cgic test

\n"); Name(); Address(); Hungry(); Temperature(); Frogs(); Color(); Flavors(); NonExButtons(); RadioButtons(); fprintf(cgiOut, "\n"); /* This value will be the exit code of the program; 0 generally indicates success among Unix and DOS programs */ return 0; Note the DEBUG #ifdef. If DEBUG is defined at compile time, either by inserting the line "#define DEBUG 1" into the program or by setting it in the Makefile or other development environment, then the cgiReadEnvironment() function will be called to restore a captured CGI environment for debugging purposes. See the discussion of the capture program, which is provided for use in CGI debugging. Outputting the Header Next, one of the cgiHeader functions should be called. In this program, cgiHeaderContentType() is called to indicate the MIME type of the document being output, in this case "text/html" (a normal HTML document). A few other common MIME types are "image/gif", "image/jpeg" and "audio/basic". Note that cgiHeaderStatus() or cgiHeaderLocation() could have been invoked instead to output an error code or redirect the request to a different URL. Only one of the cgiHeader functions should be called in a single execution of the program. Important: one of the cgiHeader functions, usually cgiHeaderContentType(), must be invoked before outputting any other response to the user. Otherwise, the result will not be a valid document and the browser's behavior will be unpredictable. You may, of course, output your own ContentType and other header information to cgiOut if you prefer. The cgiHeader functions are provided as a convenience. Next, cgiMain() invokes various functions to handle individual parts of the form. When the function is finished, it returns 0, the usual return code for a successful program. Handling Text Input The Name() function of cgictest is shown below: void Name() { char name[81]; cgiFormStringNoNewlines("name", name, 81); fprintf(cgiOut, "Name: %s
\n", name); The purpose of this function is to retrieve and display the name that was input by the user. Since the programmer has decided that names should be permitted to have up to 80 characters, a buffer of 81 characters has been declared (allowing for the final null character). The cgiFormStringNoNewlines() function is then invoked to retrieve the name and ensure that carriage returns are not present in the name (despite the incorrect behavior of some web browsers). The first argument is the name of the input field in the form, the second argument is the buffer to which the data should be copies, and the third argument is the size of the buffer. cgic will never write beyond the size of the buffer, and will always provide a null-terminated string in response; if the buffer is too small, the string will be shortened. If this is not acceptable, the cgiFormStringSpaceNeeded() function can be used to check the amount of space needed; the return value of cgiFormStringNoNewlines() can also be checked to determine whether truncation occurred. See the full description of cgiFormStringNoNewlines(). Handling Output Note that Name() writes its HTML output to cgiOut, not to stdout. Important: cgiOut is normally equivalent to stdout, and there is no performance penalty for using it. It is recommended that you write output to cgiOut to ensure compatibility with future versions of the cgic library for special environments that do not provide stdin and stdout for each cgi connection. Note that, for text input areas in which carriage returns are desired, the function cgiFormString should be used instead. cgiFormString ensures that line breaks are always represented by a single carriage return (ascii decimal 13), making life easier for the programmer. See the source code to the Address() function of cgictest.c for an example. Handling Single Checkboxes Consider the Hungry() function, which determines whether the user has selected the "hungry" checkbox: void Hungry() { if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) { fprintf(cgiOut, "I'm Hungry!
\n"); } else { fprintf(cgiOut, "I'm Not Hungry!
\n"); } This function takes advantage of the cgiFormCheckboxSingle() function, which determines whether a single checkbox has been selected. cgiFormCheckboxSingle() accepts the name attribute of the checkbox as its sole argument and returns cgiFormSuccess if the checkbox is selected, or cgiFormNotFound if it is not. If multiple checkboxes with the same name are in use, consider the cgiFormCheckboxMultiple() and cgiFormStringMultiple() functions. Handling Numeric Input Now consider the Temperature() function, which retrieves a temperature in degrees (a floating-point value) and ensures that it lies within particular bounds: void Temperature() { double temperature; cgiFormDoubleBounded("temperature", &temperature, 80.0, 120.0, 98.6); fprintf(cgiOut, "My temperature is %f.
\n", temperature); The temperature is retrieved by the function cgiFormDoubleBounded(). The first argument is the name of the temperature input field in the form; the second argument points to the address of the variable that will contain the result. The next two arguments are the lower and upper bounds, respectively. The final argument is the default value to be returned if the user did not submit a value. This function always retrieves a reasonable value within the specified bounds; values above or below bounds are constrained to fit the bounds. However, the return value of cgiFormDoubleBounded can be checked to make sure the actual user entry was in bounds, not blank, and so forth; see the description of cgiFormDoubleBounded() for more details. If bounds checking is not desired, consider using cgiFormDouble() instead. Note that, for integer input, the functions cgiFormInteger and cgiFormIntegerBounded are available. The behavior of these functions is similar to that of their floating-point counterparts above. Handling Single-Choice Input The list in the form. An array of colors is declared; the cgiFormSelectSingle() function is then invoked to determine which, if any, of those choices was selected. The first argument indicates the name of the input field in the form. The second argument points to the list of acceptable colors. The third argument indicates the number of entries in the color array. The fourth argument points to the variable which will accept the chosen color, and the last argument indicates the index of the default value to be set if no selection was submitted by the browser. cgiFormSelectSingle() will always indicate a reasonable selection value. However, if the programmer wishes to know for certain that a value was actually submitted, that the value submitted was a legal response, and so on, the return value of cgiFormSelectSingle() can be consulted. See the full description of cgiFormSelectSingle() for more information. Note that radio button groups and lists and groups of checkboxes with the same name, see the discussion of the NonExButtons() function of cgictest.c, immediately below. Handling Multiple-Choice Input Consider the first half of the NonExButtons() function of cgictest.c: char *votes[] = { "A", "B", "C", "D" }; void NonExButtons() { int voteChoices[4]; int i; int result; int invalid; char **responses; /* Method #1: check for valid votes. This is a good idea, since votes for nonexistent candidates should probably be discounted... */ fprintf(cgiOut, "Votes (method 1):
\n"); result = cgiFormCheckboxMultiple("vote", votes, 4, voteChoices, &invalid); if (result == cgiFormNotFound) { fprintf(cgiOut, "I hate them all!

\n"); } else { fprintf(cgiOut, "My preferred candidates are:\n"); fprintf(cgiOut, "

\n"); } This function takes advantage of cgiFormCheckboxMultiple(), which is used to identify one or more selected checkboxes with the same name. This function performs identically to cgiFormSelectMultiple(). That is, list). The third argument indicates the number of entries in the array of legitimate values. The fourth argument points to an array of integers with the same number of entries as the array of legitimate values; each entry will be set true if that checkbox or option was selected, false otherwise. The last argument points to an integer which will be set to the number of invalid responses (responses not in the array of valid responses) that were submitted. If this value is not of interest, the last argument may be a null pointer (0). Note that the return value of cgiFormCheckboxMultiple is inspected to determine whether any choices at all were set. See the full description of cgiFormCheckboxMultiple for other possible return values. "What if I won't know the acceptable choices at runtime?" If the acceptable choices aren't known until runtime, one can simply load the choices from disk. But if the acceptable choices aren't fixed at all (consider a list of ice cream flavors; new names may be added to the form at any time and it is inconvenient to also update program code or a separate list of countries), a more dynamic approach is needed. Consider the second half of the NonExButtons() function of cgictest.c: /* Method #2: get all the names voted for and trust them. This is good if the form will change more often than the code and invented responses are not a danger or can be checked in some other way. */ fprintf(cgiOut, "Votes (method 2):
\n"); result = cgiFormStringMultiple("vote", &responses); if (result == cgiFormNotFound) { fprintf(cgiOut, "I hate them all!

\n"); } else { int i = 0; fprintf(cgiOut, "My preferred candidates are:\n"); fprintf(cgiOut, "

\n"); } /* We must be sure to free the string array or a memory leak will occur. Simply calling free() would free the array but not the individual strings. The function cgiStringArrayFree() does the job completely. */ cgiStringArrayFree(responses); This code excerpt demonstrates an alternate means of retrieving a list of choices. The function cgiFormStringMultiple() is used to retrieve an array consisting of all the strings submitted for with a particular input field name. This works both for element that does not allow multiple selections. name should identify the NAME attribute of the element that does allow multiple selections. name should identify the NAME attribute of the