cgic: an ANSI C library for CGI Programming Need more help? Have us do it!Boutell.Com Consulting Services Home Products Open Source Accountify asftopipe Baklava CGIC Library Ciel Web Editing Email Handler Enhanced XSPF Player fax2png GD library Greasemonkey Scripts JpegAnim rinetd Search Engine smtp-after-popd SupportMeLive webthumb Short Scripts Merchant Accounts Web Tech Online Store Fun Activism Philadelphia Advertising Search Privacy About Us Consulting Contact Link To ThisTell A Friend About ThisFormat for PrintingHome Open Source CGIC Librarycgic: an ANSI C library for CGI Programmingcgic 2.05 would not compile properly due to packaging errors. This problemhas been corrected and cgic 2.05 has been reissued.If you have CGIC 1.05 or earlier, you should upgrade to CGIC 1.07,or to CGIC 2.02 or better, in order to obtain important security fixes.If you have CGIC 2.0 or CGIC 2.01 and you use the cgiCookie routines, you should upgrade to CGIC 2.02 or better, in order to obtainimportant security fixes.If you are using CGIC 2.0 through CGIC 2.05, you will want to upgradeto CGIC 2.05 to correct a file descriptor leak which can also, onsome platforms such as Windows, prevent file uploads from working.Table of ContentsCredits and license termsHow to get supportWhat's new in version XYZ of CGIC?What is cgic?Obtaining cgicBuilding and testing cgic: a sample applicationWhat to do if it won't compileHow to write a cgic applicationHow can I generate images from my cgic application?CGI debugging features: using capturecgic function referencecgic variable referencecgic result code referencecgic quick indexCredits and License Termscgic can be used free of charge, provided that acredit notice is provided online. Alternatively,a nonexclusive Commercial License can be purchased, whichgrants the right to use cgic without a public credit notice.Please see the filelicense.txtfor the details of the Basic License and Commercial License,including ordering information for the Commercial License.Thanks are due to Robert Gustavsson, Ken Holervich, Bob Nestor, Jon Ribbens, Thomas Strangert, Wu Yongwei, and other CGIC users who have corresponded over the years. Although the implementationof multipart/form-data file upload support in CGIC 2.x is my own, I particularly wish to thank those who submitted their own implementations of this feature.How to Get SupportSTOP! READ THIS FIRST! REALLY! Are you getting a "server error," indicating that your web server "cannot allow POST to this URL," or a similar message? YOU MUST CONFIGURE YOUR WEB SERVER TO ALLOW CGI PROGRAMS, AND YOU MUST INSTALL CGI PROGRAMS IN THE LOCATION (OR WITH THE EXTENSION) THAT YOUR WEB SERVER EXPECTS TO SEE. Please don't send me email about this, unless you wish me to configure your web server for you; I can certainly do that for $50/hr, but you can probably straighten this out yourself or have your web server administrator do it.Free SupportPlease submit support inquiries about CGIC via our contact page.Please note that we receive a large volume of inquiries and cannot alwaysrespond personally. Sometimesthe response must take the form of an eventualnew release or an addition to a FAQ or other document, as opposed to andetailed individual response.Hourly SupportThose requiring support in detail may arrange for direct supportfrom the author, Thomas Boutell, at the rate of $50/hr, billeddirectly by credit card. To make arrangements, contact us via ourour securemessage page. To avoid delay, be sure to specifically mentionthat you wish to purchase CGIC support at the hourly rate above.What's new in version 2.05?Temporary files used to accept file uploads were not closedproperly. This resulted in a file descriptor leak, which wasunlikely to be serious because of the short lifespan of CGI programs and the fact that very few forms upload many filesat once. However, on the Windows platform and possibly someothers, file locking semantics prevented file uploads from workingat all with these files not properly closed. Fixed in 2.05.What's new in version 2.04?Documentation fixes: the cgiHtmlEscape, cgiHtmlEscapeData,cgiValueEscape, and cgiValueEscapeData routines were namedincorrectly in the manual. No code changes in version 2.04.What's new in version 2.03?Support for setting cookies has been reimplemented. The newcode closely follows the actual practice of websites that successfullyuse cookies, rather than attempting to implement the specification.The new code can successfully set more than one cookie at a time intypical web browsers.What's new in version 2.02?In CGIC 2.0 and 2.01, if the HTTP_COOKIE environment variablewas exactly equal to the name of a cookie requested with cgiCookieString,with no value or equal sign or other characters present, a bufferoverrun could take place. This was not normal behavior and it isunknown whether any actual web server would allow it to occur, howeverwe have of course released a patch to correct it. Thanks to Nicolas Tomadakis.cgiCookieString returned cgiFormTruncated when cgiFormSuccess wouldbe appropriate. Fixed; thanks to Mathieu Villeneuve-Belair.Cookies are now set using a simpler Set-Cookie: header, and withone header line per cookie, based on data collected by Chunfu Lai. Memory leaks in cgiReadEnvironment fixed by Merezko Oleg. Thesememory leaks were not experienced in a normal CGI situation, onlywhen reading a saved CGI environment.What's new in version 2.01?Makefile supports "make install"Compiles without warnings under both C and C++ with strictwarnings and strict ANSI compliance enabledBuilds out of the box on Windows (#include <fcntl.h> was needed)Rare problem in cgiReadEnvironment corrected; no impact onnormal CGI operationscgiCookieString now sets the result to an empty stringwhen returning cgiFormNotFoundMinor code cleanupsWhat's new in version 2.0?1. CGIC 2.0 provides support for file upload fields. User-uploadedfiles are kept in temporary files, to avoid the use ofexcessive swap space (Solaris users may wish to change thecgicTempDir macro in cgic.c before compiling).The cgiFormFileName, cgiFormFileContentType, cgiFormFileSize, cgiFormFileOpen, cgiFormFileRead, andcgiFormFileClose functionsprovide a complete interface to this new functionality. Remember,the enctype attribute of the form tagmust be set to multipart/form-data when<input type="file"> tags are used.2. CGIC 2.0 provides support for setting and examining cookies(persistent data storage on the browser side).The cgiCookieString,and cgiCookieIntegerand cgiCookiesfunctions retrieve cookies. The cgiHeaderCookieSetStringand cgiHeaderCookieSetInteger functions set cookies.3. CGIC 2.0 offers a convenient way to retrieve a list of all form fields.The new cgiFormEntriesfunction performs this operation.4. CGIC 2.0 provides convenience functions to correctly escapetext before outputting it as part of HTML, or as part of the value of a tag attribute, such as the HREF orVALUE attribute. See cgiHtmlEscape,cgiHtmlEscapeData,cgiValueEscape andcgiValueEscapeData.5. Users have often asked the correct way to determine which submitbutton was clicked. This could always be accomplished in previous versions,but CGIC 2.0 also provides cgiFormSubmitClicked,a convenient alternate label for the cgiFormCheckboxSingle function.What's new in version 1.07?A problem with the cgiFormString and related functions has beencorrected. These functions were previously incorrectly returning cgiFormTruncatedin cases where the returned string fit the buffer exactly.What's new in version 1.06?1. A potentially significant buffer overflow problem has beencorrected. Jon Ribbens correctly pointed out to me (and to theInternet's bugtraq mailing list) that the cgiFormEntryStringfunction, which is used directly or indirectly by almost allCGIC programs, can potentially write past the buffer passedto it by the programmer. This bug has been corrected.Upgrading to version 1.06 is strongly recommended.2. The function cgiSaferSystem() has beenremoved entirely. This function escaped only a few metacharacters,while most shells have many, and there was no way to account forthe many different operating system shells that might be in useon different operating systems. Since this led to a false senseof security, the function has been removed. It is our recommendationthat user input should never be passed directly on the command lineunless it has been carefully shown to contain only charactersregarded as safe and appropriate by the programmer. Even then, it isbetter to design your utilities to accept their input from standardinput rather than the command line.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 Makefilenow 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 makeimplementation of that standard practical. No servertested ever rejects LF alone in this context. What's new in version 1.02?Version 1.02 corrects bugs in previous versions:cgiFormDoubleBounded specifiedits 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 compilersavailable 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 andcgiFormDoubleBounded nowaccept negative numbers properly. They also accept positivenumbers with an explicit + sign.Hex values containing the digit 9 arenow properly decoded.cgiFormString nowrepresents 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 approachpleased no one.cgiFormString andcgiFormStringNoNewlinesno longer erroneously return cgiFormEmpty in place ofcgiFormSuccess.The main() function of cgic now flushes standard outputand sleeps for one second before exiting in order to inhibitproblems with the completion of I/O on some platforms. This wasnot a cgic bug per se, but has been reported as a common problemwith CGI when used with the CERN server. This change shouldimprove compatibility.The single selection example in the testform.htmlexample now works properly. This was an error in theform itself, not cgic.cgiRemoteUser andcgiRemoteIdent are nowdocumented accurately. They were reversed earlier.What is cgic?cgic is an ANSI C-language library for the creation of CGI-basedWorld Wide Web applications. For basic information aboutthe CGI standard, see the CGI documentation at NCSA.cgic performs the following tasks:Parses form data, correcting for defective and/or inconsistent browsersTransparently accepts both GET and POST form dataAccepts uploaded files as well as regular form fieldsProvides functions to set and retrieve "cookies"(browser-side persistent information)Handles line breaks in form fields in a consistent mannerProvides string, integer, floating-point, and single- andmultiple-choice functions to retrieve form dataProvides bounds checking for numeric fieldsLoads CGI environment variables into C strings which are always non-nullProvides a way to capture CGI situations for replay in a debuggingenvironment, including file uploads and cookiescgic is compatible with any CGI-compliant server environment, andcompiles without modification in Posix/Unix/Linux and Windowsenvironments.Obtaining cgiccgic is distributed via the web in two forms: as a Windows-compatible.ZIP file, and as a gzipped tar file. Most users of Windows andrelated operating systems have access to 'unzip' or 'pkunzip'. All modern Unix systems come with 'gunzip' and 'tar' as standard equipment, and gzip/gunzipis not difficult to find if yours does not. Versionsof these programs for other operating systems are widelyavailable if you do not already have them.Important: to use cgic, you will need an ANSI-standardC compiler. Under Unix, just obtain and use gcc. Most Unix systems havestandardiszed on gcc. Users of Windows operating systems should not haveANSI C-related problems as all of the popular compilers follow the ANSI standard.Note for Windows Programmers: you must use a modern32-bit compiler. Visual C++ 2.0 or higher, Borland C++ and themingw32 gcc compiler are all appropriate, as is cygwin. Do NOT use an ancient 16-bit DOS executable compiler, please.What Operating System Does Your WEB SERVER Run?Remember, the computer on your desk is usually NOT your web server.Compiling a Windows console executable will not give you a CGI program thatcan be installed on a Linux-based server. Your web browser should inquire whether to save the file to diskwhen you select one of the links below. Under Unix and compatibleoperating systems, save it, then issue the followingcommands to unpack it:gunzip cgic205.tar.gztar -xf cgic205.tarThis should produce the subdirectory 'cgic205', which will containthe complete cgic distribution for version 2.05, including a copy of this documentation in the file cgic.html.Under Windows and compatible operating systems, save it,open a console ("DOS") window, and issue the following commands to unpack it:unzip /d cgic205.zipOr use the unzip utility of your choice.This command also produces the subdirectory 'cgic205', which will containthe complete cgic distribution for version 2.05, including a copy of this documentation in the file cgic.html.cgic is available via the web from www.boutell.com:Obtain cgic: gzipped tar fileObtain cgic: .ZIP fileBuilding cgic: a sample applicationThe sample application 'cgictest.c' is provided as part of thecgic distribution. This CGI program displays an input form, accepts a submission, and then displays what was submitted.In the process essentially all of cgic's features are tested.On a Unix system, you can build cgictest simply by typing'make cgictest.cgi'. cgic.c and cgictest.c will be compiled and linkedtogether to produce the cgictest application. Under non-Unixoperating systems, you will need to create and compile an appropriateproject containing the files cgic.c and cgictest.c. IMPORTANT: after compiling cgictest.cgi, you willneed to place it in a location on your server system which isdesignated by your server administrator as an appropriate locationfor CGI scripts. Some servers are configured to recognize anyfile ending in .cgi as a CGI program when it is found in anysubdirectory of the server's web space, but this is not alwaysthe case! The right locations for CGIprograms vary greatly from one server to another. Resolvingthis issue is between you, your web server administrator,and your web server documentation. Before submitting a bugreport for cgic, make certain that the CGI example programswhich came with your server do work for you. Otherwiseit is very likely that you have a server configuration problem.Once you have moved cgictest.cgi (or cgictest.exe, under Windows)to an appropriate cgi directory,use the web browser of your choice to access the URL at whichyou have installed it (for instance, www.mysite.com/cgi-bin/cgictest.cgi).Fill out the various fields in any manner you wish, thenselect the SUBMIT button.If all goes well, cgictest.cgi will respond with a page whichindicates the various settings you submitted. If not,please reread the section above regarding the correct location inwhich to install your CGI program on your web server.What to do if it won't compileAre you using Visual C++ or Borland C++? Did you forget to addcgic.c to your project?Make sure you are using an ANSI C or C++ compiler.(All of the Windows compilers are ANSI C compliant.)If none of the above proves effective, please see thesection regarding support.How to write a cgic applicationNote: All cgic applications must be linked to the cgic.c moduleitself. 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 initialtasks, such as parsing form data and examiningenvironment variables, the cgic library provides itsown main() function. When you write applications thatuse cgic, you will begin your own programs by writinga cgiMain() function, which cgic will invoke whenthe initial cgi work has been successfully completed. Yourprogram 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 owncode should begin with cgiMain(). The libraryprovides main() for you. (Those who prefer different behaviorcan easily modify cgic.c.)Consider the cgiMain function of cgictest.c:int cgiMain() {#ifdef DEBUG LoadEnvironment();#endif /* DEBUG */ /* Load a previously saved CGI scenario if that button has been pressed. */ if (cgiFormSubmitClicked("loadenvironment") == cgiFormSuccess) { LoadEnvironment(); } /* Set any new cookie requested. Must be done *before* outputting the content type. */ CookieSet(); /* Send the content type, letting the browser know this is HTML */ cgiHeaderContentType("text/html"); /* Top of the page */ fprintf(cgiOut, "<HTML><HEAD>\n"); fprintf(cgiOut, "<TITLE>cgic test</TITLE></HEAD>\n"); fprintf(cgiOut, "<BODY><H1>cgic test</H1>\n"); /* If a submit button has already been clicked, act on the submission of the form. */ if ((cgiFormSubmitClicked("testcgic") == cgiFormSuccess) || cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess) { HandleSubmit(); fprintf(cgiOut, "<hr>\n"); } /* Now show the form */ ShowForm(); /* Finish up the page */ fprintf(cgiOut, "</BODY></HTML>\n"); return 0;}Note the DEBUG #ifdef. If DEBUG is defined at compile time, either byinserting the line "#define DEBUG 1" into the program or by settingit in the Makefile or other development environment, then theLoadEnvironment function is invoked. This function calls cgiReadEnvironment() to restore a captured CGI environment for debugging purposes. Seealso the discussion of the capture program, which isprovided for use in CGI debugging. Because this is a test program,the cgiFormSubmitClicked function isalso called to check for the use of a button that requests the reloadingof a saved CGI environment. A completed CGI program typically wouldnever allow the end user to make that decision.Setting CookiesNext, one of the cgiHeader functions should be called.This particular program demonstrates many features, includingthe setting of cookies. If the programmer wishes to set a cookie,the cookie-setting function must be calledfirst, before other headers are output. This is done by theCookieSet() function of cgictest.c:void CookieSet(){ char cname[1024]; char cvalue[1024]; /* Must set cookies BEFORE calling cgiHeaderContentType */ cgiFormString("cname", cname, sizeof(cname)); cgiFormString("cvalue", cvalue, sizeof(cvalue)); if (strlen(cname)) { /* Cookie lives for one day (or until browser chooses to get rid of it, which may be immediately), and applies only to this script on this site. */ cgiHeaderCookieSetString(cname, cvalue, 86400, cgiScriptName, cgiServerName); }}Since this is a test program, the cgiFormString function is used to fetch the name and value from the form previously filledin by the user. Normally, cookie names and values are chosen to meet theneeds of the programmer and provide a means of identifying the sameuser again later.The cgiHeaderCookieSetStringfunction sets the cookie by requesting that the web browser store it.There is never any guarantee that this will happen!Many browsers reject cookies completely; others do not necessarily keepthem as long as requested or return them with their values intact.Always code defensively when using cookies.The cname and cvalue parameters are of course the namd and value forthe cookie. The third argument is the time, in seconds, that thecookie should "live" on the browser side before it expires; in thiscase it has been set to 86,400 seconds, which is exactly one day. The browser may or may not respect this setting, as with everythingelse about cookies.The fourth argument identifies the "path" within the website for whichthe cookie is considered valid. A cookie that should be sent backfor every access to the site should be set with a path of /.In this case the cookie is relevant only to the CGI program itself, socgiScriptName (the URL of the CGI program, not including thedomain name) is sent. Similarly, a cookie can be considered relevantto a single website or to an entire domain, such as www.boutell.com or the entire .boutell.comdomain. In this case, the current site on which the program is runningis the only relevant site, so cgiServerName is usedas the domain.Outputting the Content Type HeaderNext, 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/wav". Note that cgiHeaderStatus() or cgiHeaderLocation() could havebeen invoked instead to output an error code or redirect therequest to a different URL. Only one of the cgiHeader functionsshould be called in a single execution of the program.Important: one of the cgiHeader functions,usually cgiHeaderContentType(), must be invoked before outputting any otherresponse to the user. Otherwise, the result will not be a validdocument and the browser's behavior will be unpredictable.You may, of course, output your own ContentType and otherheader information to cgiOut if you prefer. The cgiHeader functionsare provided as a convenience.Handling Form SubmissionsLike many CGI programs, cgictest makes decisions about the way itshould behave based on whether various submit buttons have been clicked.When either the testcgic or saveenvironment button is present, cgictestinvokes the HandleSubmit function, which invokes additional functions tohandle various parts of the form:void HandleSubmit(){ Name(); Address(); Hungry(); Temperature(); Frogs(); Color(); Flavors(); NonExButtons(); RadioButtons(); File(); Entries(); Cookies(); /* The saveenvironment button, in addition to submitting the form, also saves the resulting CGI scenario to disk for later replay with the 'load saved environment' button. */ if (cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess) { SaveEnvironment(); }}Handling Text InputThe Name() function of cgictest is shown below, in its simplestpossible form:void Name() { char name[81]; cgiFormStringNoNewlines("name", name, 81); fprintf(cgiOut, "Name: "); cgicHtmlEscape(name); fprintf(cgiOut, "\n");}The purpose of this function is to retrieve and display the name that wasinput by the user. Since the programmer has decided that names shouldbe permitted to have up to 80 characters, a buffer of 81 charactershas been declared (allowing for the final null character). The cgiFormStringNoNewlines()function is then invoked to retrieve the name and ensure thatcarriage returns are not present in the name (despite theincorrect behavior of some web browsers). The first argumentis the name of the input field in the form, the second argumentis the buffer to which the data should be copied, and the thirdargument is the size of the buffer. cgic will never write beyondthe size of the buffer, and will always provide a null-terminatedstring in response; if the buffer is too small, the string willbe shortened. If this is not acceptable, thecgiFormStringSpaceNeeded()function can be used to check the amount of space needed; thereturn value of cgiFormStringNoNewlines() can also be checkedto determine whether truncation occurred. Seethe full description of cgiFormStringNoNewlines().Handling OutputNote that Name() writes its HTML output to cgiOut, notto stdout.The actual name submitted by the user may or may not containcharacters that have special meaning in HTML, specifically thethe <, >, and & characters.The cgiHtmlEscape function is used to outputthe user-entered name with any occurrences of these characterscorrectly escaped as <, >, and &.Important: cgiOut is normally equivalentto stdout, and there is no performance penalty for using it.It is recommended that you write output to cgiOut to ensure compatibilitywith modified versions of the cgic library for specialenvironments that do not provide stdin and stdout foreach cgi connection.Note that, for text input areas in which carriage returns aredesired, the function cgiFormStringshould be used instead. cgiFormString ensures that line breaksare always represented by a single carriage return (ascii decimal 13),making life easier for the programmer. See the source code tothe Address() function of cgictest.c for an example.Handling Single CheckboxesConsider the Hungry() function, which determines whetherthe user has selected the "hungry" checkbox:void Hungry() { if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) { fprintf(cgiOut, "I'm Hungry!<BR>\n"); } else { fprintf(cgiOut, "I'm Not Hungry!<BR>\n"); }}This function takes advantage of thecgiFormCheckboxSingle() function, whichdetermines whether a single checkbox has been selected. cgiFormCheckboxSingle() accepts the name attribute of the checkboxas 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 InputNow consider the Temperature() function, which retrievesa temperature in degrees (a floating-point value) and ensuresthat it lies within particular bounds:void Temperature() { double temperature; cgiFormDoubleBounded("temperature", &temperature, 80.0, 120.0, 98.6); fprintf(cgiOut, "My temperature is %f.<BR>\n", temperature);}The temperature is retrieved by the function cgiFormDoubleBounded(). The firstargument 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 upperbounds, respectively. The final argument is the default value tobe returned if the user did not submit a value.This function always retrieves a reasonable value within thespecified bounds; values above or below bounds are constrainedto fit the bounds. However, the return value ofcgiFormDoubleBounded can be checked to make sure theactual user entry was in bounds, not blank, and so forth;see the description of cgiFormDoubleBounded() for more details. If bounds checkingis not desired, consider using cgiFormDouble() instead.Note that, for integer input, the functionscgiFormInteger andcgiFormIntegerBoundedare available. The behavior of these functions is similar tothat of their floating-point counterparts above.Handling Single-Choice InputThe <SELECT> tag of HTML is used to provide the user withseveral choices. Radio buttons and checkboxes can also be usedwhen the number of choices is relatively small. Considerthe Color() function of cgictest.c:char *colors[] = { "Red", "Green", "Blue"};void Color() { int colorChoice; cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0); fprintf(cgiOut, "I am: %s<BR>\n", colors[colorChoice]);}This function determines which of several colors the user chosefrom a <SELECT> list in the form. An array of colors isdeclared; the cgiFormSelectSingle()function is then invoked to determine which, if any, of those choiceswas selected. The first argument indicates the name of the inputfield in the form. The second argument points to the list ofacceptable colors. The third argument indicates the number ofentries in the color array. The fourth argument points to thevariable which will accept the chosen color, and the last argumentindicates the index of the default value to be set if noselection was submitted by the browser. cgiFormSelectSingle() willalways indicate a reasonable selection value. However, ifthe programmer wishes to know for certain that a value wasactually submitted, that the value submitted was a legalresponse, and so on, the return value of cgiFormSelectSingle()can be consulted. See the full description ofcgiFormSelectSingle() formore information.Note that radio button groups and <SELECT> lists can bothbe handled by this function. If you are processing radiobutton groups, you may prefer to invoke cgiFormRadio(), which functionsidentically. "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 acceptablechoices aren't fixed at all (consider a list of country names;new names may be added to the form at any time and it isinconvenient to also update program code or a separate listof countries), simply invoke cgiFormStringNoNewlines()instead to retrieve the string directly. Keep in mind that, ifyou do so, validating the response to make sure it issafe and legitimate becomes a problem for your ownprogram to solve. The advantage of cgiFormSelectSingle() is that invalid responses are never returned.To handle multiple-selection <SELECT> lists andgroups of checkboxes with the same name, see thediscussion of the NonExButtons() function of cgictest.c, immediately below.Handling Multiple-Choice InputConsider 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):<BR>\n"); result = cgiFormCheckboxMultiple("vote", votes, 4, voteChoices, &invalid); if (result == cgiFormNotFound) { fprintf(cgiOut, "I hate them all!<p>\n"); } else { fprintf(cgiOut, "My preferred candidates are:\n"); fprintf(cgiOut, "<ul>\n"); for (i=0; (i < 4); i++) { if (voteChoices[i]) { fprintf(cgiOut, "<li>%s\n", votes[i]); } } fprintf(cgiOut, "</ul>\n"); }This function takes advantage ofcgiFormCheckboxMultiple(),which is used to identify one or more selected checkboxes with the same name. This function performs identically tocgiFormSelectMultiple().That is, <SELECT> tags with the MULTIPLE attribute are handledjust like a group of several checkboxes with the same name.The first argument to cgiFormCheckboxMultiple() is the name given to allcheckbox input fields in the group. The second argumentpoints to an array of legitimate values; these shouldcorrespond to the VALUE attributes of the checkboxes(or OPTION tags in a <SELECT> list). The third argumentindicates the number of entries in the array oflegitimate values. The fourth argument points toan array of integers with the same number of entriesas the array of legitimate values; each entrywill 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 ofvalid responses) that were submitted. If this value is notof interest, the last argument may be a null pointer (0).Note that the return value of cgiFormCheckboxMultiple isinspected to determine whether any choices at all wereset. See the full description ofcgiFormCheckboxMultiplefor 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 acceptablechoices 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 isinconvenient to also update program code or a separate listof countries), a more dynamic approach is needed. Considerthe 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):<BR>\n"); result = cgiFormStringMultiple("vote", &responses); if (result == cgiFormNotFound) { fprintf(cgiOut, "I hate them all!<p>\n"); } else { int i = 0; fprintf(cgiOut, "My preferred candidates are:\n"); fprintf(cgiOut, "<ul>\n"); while (responses[i]) { fprintf(cgiOut, "<li>%s\n", responses[i]); i++; } fprintf(cgiOut, "</ul>\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 retrievinga list of choices. The functioncgiFormStringMultiple() is usedto retrieve an array consisting of all the strings submittedfor with a particular input field name. This works both for<SELECT> tags with the MULTIPLE attribute and for groups of checkboxes with the same name. The first argument to cgiFormStringMultiple() is the name of the input field orgroup of input fields in question. The second argument shouldbe the address of a pointer to a pointer to a string, whichisn't as bad as it sounds. Consider the following simple callof the function:/* An array of strings; each C string is an array of characters */char **responses; cgiFormStringMultiple("vote", &responses);"How do I know how many responses there are?"After the call, the last entry in the string array will bea null pointer. Thus the simple loop:int i = 0;while (responses[i]) { /* Do something with the string responses[i] */ i++;}can be used to walk through the array until the lastentry is encountered.Important: the cgiFormStringMultiple functionreturns a pointer to allocated memory. Your codeshould not modify the strings in the responses array or the responsesarray itself; if modification is needed, the strings should becopied. When your code is done examining the responses array,you MUST call cgiStringArrayFree() with the array as an argument to free the memory associated with the array. Otherwise, the memory will not be available again until the program exists. Don't just call the free() function; if you do, the individual strings will not be freed.Accessing Uploaded FilesCGIC provides functions to access files that have been uploadedas part of a form submission. IMPORTANT: you MUST setthe enctype attribute of your form tagto multipart/form-data for this feature to work! For anexample, see the ShowForm function of cgictest.c, examined below.The File function of cgictest.c takes care of receiving uploaded files:void File(){ cgiFilePtr file; char name[1024]; char contentType[1024]; char buffer[1024]; int size; int got; if (cgiFormFileName("file", name, sizeof(name)) != cgiFormSuccess) { printf("<p>No file was uploaded.<p>\n"); return; } fprintf(cgiOut, "The filename submitted was: "); cgiHtmlEscape(name); fprintf(cgiOut, "<p>\n"); cgiFormFileSize("file", &size); fprintf(cgiOut, "The file size was: %d bytes<p>\n", size); cgiFormFileContentType("file", contentType, sizeof(contentType)); fprintf(cgiOut, "The alleged content type of the file was: "); cgiHtmlEscape(contentType); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "Of course, this is only the claim the browser " "made when uploading the file. Much like the filename, " "it cannot be trusted.<p>\n"); fprintf(cgiOut, "The file's contents are shown here:<p>\n"); if (cgiFormFileOpen("file", &file) != cgiFormSuccess) { fprintf(cgiOut, "Could not open the file.<p>\n"); return; } fprintf(cgiOut, "<pre>\n"); while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) == cgiFormSuccess) { cgiHtmlEscapeData(buffer, got); } fprintf(cgiOut, "</pre>\n"); cgiFormFileClose(file);}First, the File function checks to determine the filename that wassubmitted by the user. VERY IMPORTANT: this filename may ormay not bear any relation to the real name of the file on the user'scomputer, may be deliberately manipulated with malicious intent,and should not be used for any purpose unless you havedetermined that its content is safe for your intended use and will not,at the very least, overwrite another file of importance to you, especially ifyou intend to use it as a file name on the server side. The cgic libraryitself does not use this file name for temporary storage.If the cgiFormFileName function doesnot succeed, no file was uploaded.Next, the cgiFormFileSize function is calledto determine the size of the uploaded file, in bytes.The File function then proceeds to query the content type of the uploadedfile. Files uploaded by the user have their own content type information, which may be useful in determining whether the file is an image, HTML document,word processing document, or other type of file. However,as with the filename and any other claim made by the browser,this information should not be blindly trusted. The browsermay upload a file with the name picture.jpg and thecontent type image/jpeg, but this does not guarantee that theactual file will contain a valid JPEG image suitable for display.The content type submitted by the browser can be queried using thecgiFormFileContentType function.Of course, CGIC also provides access to the actual uploded file. First, the programmer calls cgiFormFileOpen,passing the address of a cgiFilePtr object. If this functionsucceeds, the cgiFilePtr object becomes valid, and can beused in subsequent calls to cgiFormFileRead.Notice that the number of bytes read may be less than the number requested,in particular on the last successful call before cgiFormFileRead beginsto return cgiFormEOF. When cgiFormFileRead no longer returns cgiFormSuccess, the programmer calls cgiFormFileClose torelease the cgiFilePtr object.The uploaded file data may contain anything, including binary data,null characters, and so on. The example program uses the cgiHtmlEscapeData function to output thedata with any special characters that have meaning in HTML escaped.Most programs will save the uploaded information to a server-side file ordatabase.Fetching All Form EntriesFrom time to time, the programmer may not know the names of allform fields in advance. In such situations it is convenient touse the cgiFormEntries function.The Entries function of cgictest.c demonstrates the use ofcgiFormEntries:void Entries(){ char **array, **arrayStep; fprintf(cgiOut, "List of All Submitted Form Field Names:<p>\n"); if (cgiFormEntries(&array) != cgiFormSuccess) { return; } arrayStep = array; fprintf(cgiOut, "<ul>\n"); while (*arrayStep) { fprintf(cgiOut, "<li>"); cgiHtmlEscape(*arrayStep); fprintf(cgiOut, "\n"); arrayStep++; } fprintf(cgiOut, "</ul>\n"); cgiStringArrayFree(array);}The cgiFormEntries function retrieves an array of form field names.This array consists of pointers to strings, with a final null pointerto mark the end of the list. The above code illustrates one way oflooping through the returned strings. Note the final call tocgiStringArrayFree, which isessential in order to return the memory used to store the stringsand the string array.Retrieving CookiesThe Cookies function of cgictest.c displays a list of all cookiessubmitted by the browser with the current form submission, alongwith their values:void Cookies(){ char **array, **arrayStep; char cname[1024], cvalue[1024]; fprintf(cgiOut, "Cookies Submitted On This Call, With Values " "(Many Browsers NEVER Submit Cookies):<p>\n"); if (cgiCookies(&array) != cgiFormSuccess) { return; } arrayStep = array; fprintf(cgiOut, "<table border=1>\n"); fprintf(cgiOut, "<tr><th>Cookie<th>Value</tr>\n"); while (*arrayStep) { char value[1024]; fprintf(cgiOut, "<tr>"); fprintf(cgiOut, "<td>"); cgiHtmlEscape(*arrayStep); fprintf(cgiOut, "<td>"); cgiCookieString(*arrayStep, value, sizeof(value)); cgiHtmlEscape(value); fprintf(cgiOut, "\n"); arrayStep++; } fprintf(cgiOut, "</table>\n"); cgiFormString("cname", cname, sizeof(cname)); cgiFormString("cvalue", cvalue, sizeof(cvalue)); if (strlen(cname)) { fprintf(cgiOut, "New Cookie Set On This Call:<p>\n"); fprintf(cgiOut, "Name: "); cgiHtmlEscape(cname); fprintf(cgiOut, "Value: "); cgiHtmlEscape(cvalue); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "If your browser accepts cookies " "(many do not), this new cookie should appear " "in the above list the next time the form is " "submitted.<p>\n"); } cgiStringArrayFree(array);}VERY IMPORTANT: YOUR BROWSER MIGHT NOT SUBMIT COOKIES,EVER, REGARDLESS OF WHAT VALUES YOU ENTER INTO THE TEST FORM.Many, many browsers are configured not to accept or send cookies;others are configured to send them as little as possible to meet thebare minimum requirements for entry into popular sites. Users will oftenrefuse your cookies; make sure your code still works in that situation!The above code uses the cgiCookies functionto retrieve a list of all currently set cookies as a null-terminatedarray of strings. The cgiCookieStringfunction is then used to fetch the value associated with each cookie;this function works much like cgiFormString,discussed earlier. Note that a cookie set as a part of the currentform submission process does not appear on this list immediately, asit has not yet been sent back by the browser. It should appear onfuture submissions, provided that the browser chooses to acceptand resend the cookie at all.Displaying a Form That Submits to the Current ProgramCGI programmers often need to display HTML pages as part of the outputof CGI programs; these HTML pages often contain forms which should submitfields back to the same program they came from. Provided that yourweb server is well-configured, this can be done conveniently usingthe cgiScriptName environment variable, as shown below. Here is thesource code of the ShowForm function of cgictest.c:void ShowForm(){ fprintf(cgiOut, "<!-- 2.0: multipart/form-data is required "for file uploads. -->"); fprintf(cgiOut, "<form method=\"POST\" " "enctype=\"multipart/form-data\" "); fprintf(cgiOut, " action=\""); cgiValueEscape(cgiScriptName); fprintf(cgiOut, "\">\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "Text Field containing Plaintext\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "<input type=\"text\" name=\"name\">Your Name\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "Multiple-Line Text Field\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "<textarea NAME=\"address\" ROWS=4 COLS=40>\n"); fprintf(cgiOut, "Default contents go here. \n"); fprintf(cgiOut, "</textarea>\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "Checkbox\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "<input type=\"checkbox\" name=\"hungry\" checked>Hungry\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "Text Field containing a Numeric Value\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "<input type=\"text\" name=\"temperature\" value=\"98.6\">\n"); fprintf(cgiOut, "Blood Temperature (80.0-120.0)\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "Text Field containing an Integer Value\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "<input type=\"text\" name=\"frogs\" value=\"1\">\n"); fprintf(cgiOut, "Frogs Eaten\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "Single-SELECT\n"); fprintf(cgiOut, "<br>\n"); fprintf(cgiOut, "<select name=\"colors\">\n"); fprintf(cgiOut, "<option value=\"Red\">Red\n"); fprintf(cgiOut, "<option value=\"Green\">Green\n"); fprintf(cgiOut, "<option value=\"Blue\">Blue\n"); fprintf(cgiOut, "</select>\n"); fprintf(cgiOut, "<br>\n"); fprintf(cgiOut, "Multiple-SELECT\n"); fprintf(cgiOut, "<br>\n"); fprintf(cgiOut, "<select name=\"flavors\" multiple>\n"); fprintf(cgiOut, "<option value=\"pistachio\">Pistachio\n"); fprintf(cgiOut, "<option value=\"walnut\">Walnut\n"); fprintf(cgiOut, "<option value=\"creme\">Creme\n"); fprintf(cgiOut, "</select>\n"); fprintf(cgiOut, "<p>Exclusive Radio Button Group: Age of " "Truck in Years\n"); fprintf(cgiOut, "<input type=\"radio\" name=\"age\" " "value=\"1\">1\n"); fprintf(cgiOut, "<input type=\"radio\" name=\"age\" " "value=\"2\">2\n"); fprintf(cgiOut, "<input type=\"radio\" name=\"age\" " "value=\"3\" checked>3\n"); fprintf(cgiOut, "<input type=\"radio\" name=\"age\" " "value=\"4\">4\n"); fprintf(cgiOut, "<p>Nonexclusive Checkbox Group: " "Voting for Zero through Four Candidates\n"); fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" " "value=\"A\">A\n"); fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" " "value=\"B\">B\n"); fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" " "value=\"C\">C\n"); fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" " "value=\"D\">D\n"); fprintf(cgiOut, "<p>File Upload:\n"); fprintf(cgiOut, "<input type=\"file\" name=\"file\" " "value=\"\"> (Select A Local File)\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut, "<p>Set a Cookie<p>\n"); fprintf(cgiOut, "<input name=\"cname\" " "value=\"\"> Cookie Name\n"); fprintf(cgiOut, "<input name=\"cvalue\" " "value=\"\"> Cookie Value<p>\n"); fprintf(cgiOut, "<input type=\"submit\" " "name=\"testcgic\" value=\"Submit Request\">\n"); fprintf(cgiOut, "<input type=\"reset\" " "value=\"Reset Request\">\n"); fprintf(cgiOut, "<p>Save the CGI Environment<p>\n"); fprintf(cgiOut, "Pressing this button will submit the form, then " "save the CGI environment so that it can be replayed later " "by calling cgiReadEnvironment (in a debugger, for " "instance).<p>\n"); fprintf(cgiOut, "<input type=\"submit\" name=\"saveenvironment\" " "value=\"Save Environment\">\n"); fprintf(cgiOut, "</form>\n");}Note the use of enctype="multipart/form-data" in theFORM tag. This is absolutely required if the formwill contain file upload fields, as in the above example. Mostbrowsers will not even attempt file uploads without thepresence of this attribute.Examining CGI environment variablesThe CGI standard specifies a number of environment variableswhich are set by the server. However, servers are somewhatunpredictable as to whether these variables will be null orpoint to empty strings when an environment variable is not set.Also, in order to allow the programmer to restore savedCGI environments, the cgic library needs have a way of insulatingthe programmer from the actual environment variables.Instead of calling getenv() to determine the value of avariable such as HTTP_USER_AGENT (the browser software being used),always use thecgic copies of the environment variables,which are always valid C strings (they are never null, althoughthey may point to an empty string). For instance, the cgicvariable containing the name of the browser software iscgiUserAgent. The referring URL appearsin the variable cgiReferrer.How can I generate images from my cgic application?cgic can be used in conjunction with thegd graphics library, whichcan produce GIF images on the fly.The following short sample program hints at the possibilities:#include "cgic.h"#include "gd.h"char *colors[] = { "red", "green", "blue"};#define colorsTotal 3int cgiMain() { int colorChosen; gdImagePtr im; int r, g, b; /* Use gd to create an image */ im = gdImageCreate(64, 64); r = gdImageColorAllocate(im, 255, 0, 0); g = gdImageColorAllocate(im, 0, 255, 0); b = gdImageColorAllocate(im, 0, 0, 255); /* Now use cgic to find out what color the user requested */ cgiFormSelectSingle("color", 3, &colorChosen, 0); /* Now fill with the desired color */ switch(colorChosen) { case 0: gdImageFill(im, 32, 32, r); break; case 1: gdImageFill(im, 32, 32, g); break; case 2: gdImageFill(im, 32, 32, b); break; } /* Now output the image. Note the content type! */ cgiHeaderContentType("image/gif"); /* Send the image to cgiOut */ gdImageGif(im, cgiOut); /* Free the gd image */ gdImageDestroy(im); return 0;}Note that this program would need to be linked with both cgic.oand libgd.a. Often programs of this type respond to onecgiPathInfo value or set of form fields by returning an HTML page with an inline image reference that, in turn, generates a GIF image.Debugging CGI applications: using captureDebugging CGI applications can be a painful task. Since CGI applicationsrun in a special environment created by the web server, it is difficultto execute them in a debugger. However, the cgic library provides a way of capturing "live" CGI environments to a file, and also provides a wayto reload saved environments. The provided program 'capture.c' can be used to capture CGIenvironments. Just change the first line of the cgiMain() functionof capture.c to save the CGI environment to a filename appropriateon your system and type 'make capture'. Then place capture in yourcgi directory and set the form action or other link you want to testto point to it. When the form submission or other link takes place,capture will write the CGI environment active at that time tothe filename you specified in the source. ThecgiReadEnvironment() function can then be invoked on the same filename at the beginning of the cgiMain() function of the application you want to test in order to restore the captured environment. You can then execute your program in the debugger of your choice,and it should perform exactly as it would have performed hadit been launched by the actual web server, including file uploads,cookies and all other phenomena within the purview of cgic.Important: Make sure you specify the full path, as thecurrent working directory of a CGI script may not be what youthink it is!Even More Important: If you call getenv() yourselfin your code, instead of using the provided cgic copies of the CGI environment variables, you willnot get the values you expect when running witha saved CGI environment. Always use the cgic variables insteadof calling getenv().cgic function referencecgiFormResultType cgiFormString( char *name, char *result, int max)cgiFormString attempts to retrieve the string sent for the specified input field. The text will be copied into the buffer specified by result, up to but not exceeding max-1 bytes; a terminating null is then added to complete the string. Regardless of the newline format submitted by the browser, cgiFormString always encodes each newline as a single line feed (ascii decimal 10); as a result the final string may be slightly shorter than indicated by a call to cgiFormStringSpaceNeeded but will never be longer. cgiFormString returns cgiFormSuccess if the string was successfully retrieved, cgiFormTruncated if the string was retrieved but was truncated to fit the buffer, cgiFormEmpty if the string was retrieved but was empty, and cgiFormNotFound if no such input field was submitted. In the last case, an empty string is copied to result. cgiFormResultType cgiFormStringNoNewlines( char *name, char *result, int max)cgiFormStringNoNewlines() is exactly equivalent to cgiFormString(), except that any carriage returns or line feeds that occur in the input will be stripped out. The use of this function is recommended for single-line text input fields, as some browsers will submit carriage returns and line feeds when they should not. cgiFormResultType cgiFormStringSpaceNeeded( char *name, int *length)cgiFormStringSpaceNeeded() is used to determine the length of the input text buffer needed to receive the contents of the specified input field. This is useful if the programmer wishes to allocate sufficient memory for input of arbitrary length. The actual length of the string retrieved by a subsequent call to cgiFormString() may be slightly shorter but will never be longer than *result. On success, cgiFormStringSpaceNeeded() sets the value pointed to by length to the number of bytes of data, including the terminating null, and returns cgiFormSuccess. If no value was submitted for the specified field, cgiFormStringSpaceNeeded sets the value pointed to by length to 1 and returns cgiFormNotFound. 1 is set to ensure space for an empty string (a single null character) if cgiFormString is called despite the return value.cgiFormResultType cgiFormStringMultiple( char *name, char ***ptrToStringArray)cgiFormStringMultiple is useful in the unusual case in which several input elements in the form have the same name and, for whatever reason, the programmer does not wish to use the checkbox, radio button and selection menu functions provided below. This is occasionally needed if the programmer cannot know in advance what values might appear in a multiple-selection list or group of checkboxes on a form. The value pointed to by result will be set to a pointer to an array of strings; the last entry in the array will be a null pointer. This array is allocated by the CGI library. Important: when done working with the array, you must call cgiStringArrayFree() with the array pointer as the argument. cgiFormStringMultiple() returns cgiFormSuccess if at least one occurrence of the name is found, cgiFormNotFound if no occurrences are found, or cgiFormMemory if not enough memory is available to allocate the array to be returned. In all cases except the last, ptrToStringArray is set to point to a valid array of strings, with the last element in the array being a null pointer; in the out-of-memory case ptrToStringArray is set to a null pointer.cgiFormResultType cgiFormEntries( char ***ptrToStringArray)cgiFormEntries is useful when the programmer cannot know the names of all relevant form fields in advance. The value pointed to by result will be set to a pointer to an array of strings; the last entry in the array will be a null pointer. This array is allocated by the CGI library. Important: when done working with the array, you must call cgiStringArrayFree() with the array pointer as the argument. cgiFormEntries() returns cgiFormSuccess except in the event of an out of memory error. On success, ptrToStringArray is set to point to a valid array of strings, with the last element in the array being a null pointer; in the out-of-memory case ptrToStringArray is set to a null pointer, and cgiFormOutOfMemory is returned.void cgiStringArrayFree(char **stringArray)cgiStringArrayFree() is used to free the memory associated with a string array created by cgiFormStringMultiple(), cgiFormEntries(), or cgiFormCookies().cgiFormResultType cgiFormInteger( char *name, int *result, int defaultV)cgiFormInteger() attempts to retrieve the integer sent for the specified input field. The value pointed to by result will be set to the value submitted. cgiFormInteger() returns cgiFormSuccess if the value was successfully retrieved, cgiFormEmpty if the value submitted is an empty string, cgiFormBadType if the value submitted is not an integer, and cgiFormNotFound if no such input field was submitted. In the last three cases, the value pointed to by result is set to the specified default.cgiFormResultType cgiFormIntegerBounded( char *name, int *result, int min, int max, int defaultV)cgiFormIntegerBounded() attempts to retrieve the integer sent for the specified input field, and constrains the result to be within the specified bounds. The value pointed to by result will be set to the value submitted. cgiFormIntegerBounded() returns cgiFormSuccess if the value was successfully retrieved, cgiFormConstrained if the value was out of bounds and result was adjusted accordingly, cgiFormEmpty if the value submitted is an empty string, cgiFormBadType if the value submitted is not an integer, and cgiFormNotFound if no such input field was submitted. In the last three cases, the value pointed to by result is set to the specified default.cgiFormResultType cgiFormDouble( char *name, double *result, double defaultV)cgiFormDouble attempts to retrieve the floating-point value sent for the specified input field. The value pointed to by result will be set to the value submitted. cgiFormDouble returns cgiFormSuccess if the value was successfully retrieved, cgiFormEmpty if the value submitted is an empty string, cgiFormBadType if the value submitted is not a number, and cgiFormNotFound if no such input field was submitted. In the last three cases, the value pointed to by result is set to the specified default. cgiFormResultType cgiFormDoubleBounded( char *name, double *result, double min, double max, double defaultV)cgiFormDoubleBounded() attempts to retrieve the floating-point value sent for the specified input field, and constrains the result to be within the specified bounds. The value pointed to by result will be set to the value submitted. cgiFormDoubleBounded() returns cgiFormSuccess if the value was successfully retrieved, cgiFormConstrained if the value was out of bounds and result was adjusted accordingly, cgiFormEmpty if the value submitted is an empty string, cgiFormBadType if the value submitted is not a number, and cgiFormNotFound if no such input field was submitted. In the last three cases, the value pointed to by result is set to the specified default. cgiFormResultType cgiFormSelectSingle( char *name, char **choicesText, int choicesTotal, int *result, int defaultV)cgiFormSelectSingle() retrieves the selection number associated with a <SELECT> element that does not allow multiple selections. name should identify the NAME attribute of the <SELECT> element. choicesText should point to an array of strings identifying each choice; choicesTotal should indicate the total number of choices. The value pointed to by result will be set to the position of the actual choice selected within the choicesText array, if any, or to the value of default, if no selection was submitted or an invalid selection was made. cgiFormSelectSingle() returns cgiFormSuccess if the value was successfully retrieved, cgiFormNotFound if no selection was submitted, and cgiFormNoSuchChoice if the selection does not match any of the possibilities in the choicesText array. cgiFormResultType cgiFormSelectMultiple( char *name, char **choicesText, int choicesTotal, int *result, int *invalid)cgiFormSelectMultiple() retrieves the selection numbers associated with a <SELECT> element that does allow multiple selections. name should identify the NAME attribute of the <SELECT> element. choicesText should point to an array of strings identifying each choice; choicesTotal should indicate the total number of choices. result should point to an array of integers with as many elements as there are strings in the choicesText array. For each choice in the choicesText array that is selected, the corresponding integer in the result array will be set to one; other entries in the result array will be set to zero. cgiFormSelectMultiple() returns cgiFormSuccess if at least one valid selection was successfully retrieved or cgiFormNotFound if no valid selections were submitted. The integer pointed to by invalid is set to the number of invalid selections that were submitted, which should be zero unless the form and the choicesText array do not agree.cgiFormResultType cgiFormSubmitClicked( char *name)It is often desirable to know whether a particular submit button was clicked, when multiple submit buttons with different name attributes exist. cgiFormSubmitClicked is an alternative name for the cgiFormCheckboxSingle function, which is suitable for testing whether a particular submit button was used.cgiFormResultType cgiFormCheckboxSingle( char *name)cgiFormCheckboxSingle determines whether the checkbox with the specified name is checked. cgiFormCheckboxSingle returns cgiFormSuccess if the button is checked, cgiFormNotFound if the checkbox is not checked. cgiFormCheckboxSingle is intended for single checkboxes with a unique name; see below for functions to deal with multiple checkboxes with the same name, and with radio buttons.cgiFormResultType cgiFormCheckboxMultiple( char *name, char **valuesText, int valuesTotal, int *result, int *invalid)cgiFormCheckboxMultiple() determines which checkboxes among a group of checkboxes with the same name are checked. This is distinct from radio buttons (see cgiFormRadio). valuesText should point to an array of strings identifying the VALUE attribute of each checkbox; valuesTotal should indicate the total number of checkboxes. result should point to an array of integers with as many elements as there are strings in the valuesText array. For each choice in the valuesText array that is selected, the corresponding integer in the result array will be set to one; other entries in the result array will be set to zero. cgiFormCheckboxMultiple returns cgiFormSuccess if at least one valid checkbox was checked or cgiFormNotFound if no valid checkboxes were checked. The integer pointed to by invalid is set to the number of invalid selections that were submitted, which should be zero unless the form and the valuesText array do not agree.cgiFormResultType cgiFormRadio( char *name, char **valuesText, int valuesTotal, int *result, int defaultV)cgiFormRadio() determines which, if any, of a group of radio boxes with the same name was selected. valuesText should point to an array of strings identifying the VALUE attribute of each radio box; valuesTotal should indicate the total number of radio boxes. The value pointed to by result will be set to the position of the actual choice selected within the valuesText array, if any, or to the value of default, if no radio box was checked or an invalid selection was made. cgiFormRadio() returns cgiFormSuccess if a checked radio box was found in the group, cgiFormNotFound if no box was checked, and cgiFormNoSuchChoice if the radio box submitted does not match any of the possibilities in the valuesText array.cgiFormResultType cgiFormFileName( char *name, char *fileName, int max)cgiFormFileName attempts to retrieve the file name uploaded by the user for the specified form input field of type file. NEVER, EVER TRUST THIS FILENAME TO BE REASONABLE AND SAFE FOR DIRECT USE ON THE SERVER SIDE. The text will be copied into the buffer specified by fileName, up to but not exceeding max-1 bytes; a terminating null is then added to complete the string. cgiFormFileName returns cgiFormSuccess if the string was successfully retrieved and was not empty, cgiFormNoFileName if the string was successfully retrieved but empty indicating that no file was uploaded, cgiFormTruncated if the string was retrieved but was truncated to fit the buffer, and cgiFormNotFound if no such input field was submitted. In the last case, an empty string is copied to result. cgiFormResultType cgiFormFileSize( char *name, int *sizeP)cgiFormFileSize attempts to retrieve the size, in bytes, of a file uploaded by the browser in response to the input field of type file specified by the name parameter. On success, the size is stored to *sizeP, and this function returns cgiFormSuccess. If the form field does not exist, this function returns cgiFormNotFound. If the form field exists but no file was uploaded, this function returns cgiFormNotAFile.cgiFormResultType cgiFormFileContentType( char *name, char *contentType, int max)cgiFormString attempts to retrieve the content name claimed by the user for the specified form input field of type file. THERE IS NO GUARANTEE THAT THE CONTENT TYPE WILL BE ACCURATE. The content type string will be copied into the buffer specified by contentType, up to but not exceeding max-1 bytes; a terminating null is then added to complete the string. cgiFormFileContentType returns cgiFormSuccess if the string was successfully retrieved and was not empty, cgiFormNoContentType if the string was successfully retrieved but empty indicating that no file was uploaded or the browser did not know the content type, cgiFormTruncated if the string was retrieved but was truncated to fit the buffer, and cgiFormNotFound if no such input field was submitted. In the last case, an empty string is copied to result. cgiFormResultType cgiFormFileOpen( char *name, cgiFilePtr *cfpp)cgiFormFileOpen attempts to open the actual uploaded file data for the specified form field of type file. Upon success, this function returns retrieve the content name claimed by the user for the specified form input field of type file. On success, this function sets *cfpp to a valid cgiFilePtr object for use with stripe-whoresstripe-whores stripe-whoresstripe-whores Contact UsCopyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,2004, 2005, 2006, 2007, 2008 Boutell.Com, Inc. All Rights Reserved. |
|