481 lines
14 KiB
C
481 lines
14 KiB
C
/* Change this if the SERVER_NAME environment variable does not report
|
|
the true name of your web server. */
|
|
#if 1
|
|
#define SERVER_NAME cgiServerName
|
|
#endif
|
|
#if 0
|
|
#define SERVER_NAME "www.boutell.dev"
|
|
#endif
|
|
|
|
/* You may need to change this, particularly under Windows;
|
|
it is a reasonable guess as to an acceptable place to
|
|
store a saved environment in order to test that feature.
|
|
If that feature is not important to you, you needn't
|
|
concern yourself with this. */
|
|
|
|
#ifdef WIN32
|
|
#define SAVED_ENVIRONMENT "c:\\cgicsave.env"
|
|
#else
|
|
#define SAVED_ENVIRONMENT "/tmp/cgicsave.env"
|
|
#endif /* WIN32 */
|
|
|
|
#include <stdio.h>
|
|
#include "cgic.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
void HandleSubmit();
|
|
void ShowForm();
|
|
void CookieSet();
|
|
void Name();
|
|
void Address();
|
|
void Hungry();
|
|
void Temperature();
|
|
void Frogs();
|
|
void Color();
|
|
void Flavors();
|
|
void NonExButtons();
|
|
void RadioButtons();
|
|
void File();
|
|
void Entries();
|
|
void Cookies();
|
|
void LoadEnvironment();
|
|
void SaveEnvironment();
|
|
|
|
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;
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
void Name() {
|
|
char name[81];
|
|
cgiFormStringNoNewlines("name", name, 81);
|
|
fprintf(cgiOut, "Name: ");
|
|
cgiHtmlEscape(name);
|
|
fprintf(cgiOut, "<BR>\n");
|
|
}
|
|
|
|
void Address() {
|
|
char address[241];
|
|
cgiFormString("address", address, 241);
|
|
fprintf(cgiOut, "Address: <PRE>\n");
|
|
cgiHtmlEscape(address);
|
|
fprintf(cgiOut, "</PRE>\n");
|
|
}
|
|
|
|
void Hungry() {
|
|
if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) {
|
|
fprintf(cgiOut, "I'm Hungry!<BR>\n");
|
|
} else {
|
|
fprintf(cgiOut, "I'm Not Hungry!<BR>\n");
|
|
}
|
|
}
|
|
|
|
void Temperature() {
|
|
double temperature;
|
|
cgiFormDoubleBounded("temperature", &temperature, 80.0, 120.0, 98.6);
|
|
fprintf(cgiOut, "My temperature is %f.<BR>\n", temperature);
|
|
}
|
|
|
|
void Frogs() {
|
|
int frogsEaten;
|
|
cgiFormInteger("frogs", &frogsEaten, 0);
|
|
fprintf(cgiOut, "I have eaten %d frogs.<BR>\n", frogsEaten);
|
|
}
|
|
|
|
char *colors[] = {
|
|
"Red",
|
|
"Green",
|
|
"Blue"
|
|
};
|
|
|
|
void Color() {
|
|
int colorChoice;
|
|
cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0);
|
|
fprintf(cgiOut, "I am: %s<BR>\n", colors[colorChoice]);
|
|
}
|
|
|
|
char *flavors[] = {
|
|
"pistachio",
|
|
"walnut",
|
|
"creme"
|
|
};
|
|
|
|
void Flavors() {
|
|
int flavorChoices[3];
|
|
int i;
|
|
int result;
|
|
int invalid;
|
|
result = cgiFormSelectMultiple("flavors", flavors, 3,
|
|
flavorChoices, &invalid);
|
|
if (result == cgiFormNotFound) {
|
|
fprintf(cgiOut, "I hate ice cream.<p>\n");
|
|
} else {
|
|
fprintf(cgiOut, "My favorite ice cream flavors are:\n");
|
|
fprintf(cgiOut, "<ul>\n");
|
|
for (i=0; (i < 3); i++) {
|
|
if (flavorChoices[i]) {
|
|
fprintf(cgiOut, "<li>%s\n", flavors[i]);
|
|
}
|
|
}
|
|
fprintf(cgiOut, "</ul>\n");
|
|
}
|
|
}
|
|
|
|
char *ages[] = {
|
|
"1",
|
|
"2",
|
|
"3",
|
|
"4"
|
|
};
|
|
|
|
void RadioButtons() {
|
|
int ageChoice;
|
|
char ageText[10];
|
|
/* Approach #1: check for one of several valid responses.
|
|
Good if there are a short list of possible button values and
|
|
you wish to enumerate them. */
|
|
cgiFormRadio("age", ages, 4, &ageChoice, 0);
|
|
|
|
fprintf(cgiOut, "Age of Truck: %s (method #1)<BR>\n",
|
|
ages[ageChoice]);
|
|
|
|
/* Approach #2: just get the string. Good
|
|
if the information is not critical or if you wish
|
|
to verify it in some other way. Note that if
|
|
the information is numeric, cgiFormInteger,
|
|
cgiFormDouble, and related functions may be
|
|
used instead of cgiFormString. */
|
|
cgiFormString("age", ageText, 10);
|
|
|
|
fprintf(cgiOut, "Age of Truck: %s (method #2)<BR>\n", ageText);
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
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, SERVER_NAME);
|
|
}
|
|
}
|
|
|
|
void LoadEnvironment()
|
|
{
|
|
if (cgiReadEnvironment(SAVED_ENVIRONMENT) !=
|
|
cgiEnvironmentSuccess)
|
|
{
|
|
cgiHeaderContentType("text/html");
|
|
fprintf(cgiOut, "<head>Error</head>\n");
|
|
fprintf(cgiOut, "<body><h1>Error</h1>\n");
|
|
fprintf(cgiOut, "cgiReadEnvironment failed. Most "
|
|
"likely you have not saved an environment "
|
|
"yet.\n");
|
|
exit(0);
|
|
}
|
|
/* OK, return now and show the results of the saved environment */
|
|
}
|
|
|
|
void SaveEnvironment()
|
|
{
|
|
if (cgiWriteEnvironment(SAVED_ENVIRONMENT) !=
|
|
cgiEnvironmentSuccess)
|
|
{
|
|
fprintf(cgiOut, "<p>cgiWriteEnvironment failed. Most "
|
|
"likely %s is not a valid path or is not "
|
|
"writable by the user that the CGI program "
|
|
"is running as.<p>\n", SAVED_ENVIRONMENT);
|
|
} else {
|
|
fprintf(cgiOut, "<p>Environment saved. Click this button "
|
|
"to restore it, playing back exactly the same "
|
|
"scenario: "
|
|
"<form method=POST action=\"");
|
|
cgiValueEscape(cgiScriptName);
|
|
fprintf(cgiOut, "\">"
|
|
"<input type=\"submit\" "
|
|
"value=\"Load Environment\" "
|
|
"name=\"loadenvironment\"></form><p>\n");
|
|
}
|
|
}
|
|
|