📄 cgi.c
字号:
invalidE++;
}
} while ((e = cgiFormEntryFindNext()) != 0);
*invalid = invalidE;
if (hits) {
return cgiFormSuccess;
} else {
return cgiFormNotFound;
}
}
cgiFormResultType cgiFormCheckboxSingle(
char *name)
{
cgiFormEntry *e;
e = cgiFormEntryFindFirst(name);
if (!e) {
return cgiFormNotFound;
}
return cgiFormSuccess;
}
extern cgiFormResultType cgiFormCheckboxMultiple(
char *name, char **valuesText, int valuesTotal,
int *result, int *invalid)
{
/* Implementation is identical to cgiFormSelectMultiple. */
return cgiFormSelectMultiple(name, valuesText,
valuesTotal, result, invalid);
}
cgiFormResultType cgiFormRadio(
char *name,
char **valuesText, int valuesTotal, int *result, int defaultV)
{
/* Implementation is identical to cgiFormSelectSingle. */
return cgiFormSelectSingle(name, valuesText, valuesTotal,
result, defaultV);
}
cgiFormResultType cgiCookieString(
char *name,
char *value,
int space)
{
char *p = cgiCookie;
while (*p) {
char *n = name;
/* 2.02: if cgiCookie is exactly equal to name, this
can cause an overrun. The server probably wouldn't
allow it, since a name without values makes no sense
-- but then again it might not check, so this is a
genuine security concern. Thanks to Nicolas
Tomadakis. */
while (*p == *n) {
if ((p == '\0') && (n == '\0')) {
/* Malformed cookie header from client */
return cgiFormNotFound;
}
p++;
n++;
}
if ((!*n) && (*p == '=')) {
p++;
while ((*p != ';') && (*p != '\0') &&
(space > 1))
{
*value = *p;
value++;
p++;
space--;
}
if (space > 0) {
*value = '\0';
}
/* Correct parens: 2.02. Thanks to
Mathieu Villeneuve-Belair. */
if (!(((*p) == ';') || ((*p) == '\0')))
{
return cgiFormTruncated;
} else {
return cgiFormSuccess;
}
} else {
/* Skip to next cookie */
while (*p) {
if (*p == ';') {
break;
}
p++;
}
if (!*p) {
/* 2.01: default to empty */
if (space) {
*value = '\0';
}
return cgiFormNotFound;
}
p++;
/* Allow whitespace after semicolon */
while ((*p) && isspace(*p)) {
p++;
}
}
}
/* 2.01: actually the above loop never terminates except
with a return, but do this to placate gcc */
if (space) {
*value = '\0';
}
return cgiFormNotFound;
}
cgiFormResultType cgiCookieInteger(
char *name,
int *result,
int defaultV)
{
char buffer[256];
cgiFormResultType r =
cgiCookieString(name, buffer, sizeof(buffer));
if (r != cgiFormSuccess) {
*result = defaultV;
} else {
*result = atoi(buffer);
}
return r;
}
void cgiHeaderCookieSetInteger(char *name, int value, int secondsToLive,
char *path, char *domain)
{
char svalue[256];
sprintf(svalue, "%d", value);
cgiHeaderCookieSetString(name, svalue, secondsToLive, path, domain);
}
char *days[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
};
char *months[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
void cgiHeaderCookieSetString(char *name, char *value, int secondsToLive,
char *path, char *domain)
{
/* cgic 2.02: simpler and more widely compatible implementation.
Thanks to Chunfu Lai.
cgic 2.03: yes, but it didn't work. Reimplemented by
Thomas Boutell. ; after last element was a bug.
Examples of real world cookies that really work:
Set-Cookie: MSNADS=UM=; domain=.slate.com;
expires=Tue, 26-Apr-2022 19:00:00 GMT; path=/
Set-Cookie: MC1=V=3&ID=b5bc08af2b8a43ff85fcb5efd8b238f0;
domain=.slate.com; expires=Mon, 04-Oct-2021 19:00:00 GMT; path=/
*/
time_t now;
time_t then;
struct tm *gt;
time(&now);
then = now + secondsToLive;
gt = gmtime(&then);
fprintf(cgiOut,
"Set-Cookie: %s=%s; domain=%s; expires=%s, %02d-%s-%04d %02d:%02d:%02d GMT; path=%s\r\n",
name, value, domain,
days[gt->tm_wday],
gt->tm_mday,
months[gt->tm_mon],
gt->tm_year + 1900,
gt->tm_hour,
gt->tm_min,
gt->tm_sec,
path);
}
void cgiHeaderLocation(char *redirectUrl) {
fprintf(cgiOut, "Location: %s\r\n\r\n", redirectUrl);
}
void cgiHeaderStatus(int status, char *statusMessage) {
fprintf(cgiOut, "Status: %d %s\r\n\r\n", status, statusMessage);
}
void cgiHeaderContentType(char *mimeType) {
fprintf(cgiOut, "Content-type: %s\r\n\r\n", mimeType);
}
static int cgiWriteString(FILE *out, char *s);
static int cgiWriteInt(FILE *out, int i);
#define CGIC_VERSION "2.0"
cgiEnvironmentResultType cgiWriteEnvironment(char *filename) {
FILE *out;
cgiFormEntry *e;
/* Be sure to open in binary mode */
out = fopen(filename, "wb");
if (!out) {
/* Can't create file */
return cgiEnvironmentIO;
}
if (!cgiWriteString(out, "CGIC2.0")) {
goto error;
}
if (!cgiWriteString(out, cgiServerSoftware)) {
goto error;
}
if (!cgiWriteString(out, cgiServerName)) {
goto error;
}
if (!cgiWriteString(out, cgiGatewayInterface)) {
goto error;
}
if (!cgiWriteString(out, cgiServerProtocol)) {
goto error;
}
if (!cgiWriteString(out, cgiServerPort)) {
goto error;
}
if (!cgiWriteString(out, cgiRequestMethod)) {
goto error;
}
if (!cgiWriteString(out, cgiPathInfo)) {
goto error;
}
if (!cgiWriteString(out, cgiPathTranslated)) {
goto error;
}
if (!cgiWriteString(out, cgiScriptName)) {
goto error;
}
if (!cgiWriteString(out, cgiQueryString)) {
goto error;
}
if (!cgiWriteString(out, cgiRemoteHost)) {
goto error;
}
if (!cgiWriteString(out, cgiRemoteAddr)) {
goto error;
}
if (!cgiWriteString(out, cgiAuthType)) {
goto error;
}
if (!cgiWriteString(out, cgiRemoteUser)) {
goto error;
}
if (!cgiWriteString(out, cgiRemoteIdent)) {
goto error;
}
if (!cgiWriteString(out, cgiContentType)) {
goto error;
}
if (!cgiWriteString(out, cgiAccept)) {
goto error;
}
if (!cgiWriteString(out, cgiUserAgent)) {
goto error;
}
if (!cgiWriteString(out, cgiReferrer)) {
goto error;
}
if (!cgiWriteString(out, cgiCookie)) {
goto error;
}
if (!cgiWriteInt(out, cgiContentLength)) {
goto error;
}
e = cgiFormEntryFirst;
while (e) {
cgiFilePtr fp;
if (!cgiWriteString(out, e->attr)) {
goto error;
}
if (!cgiWriteString(out, e->value)) {
goto error;
}
/* New 2.0 fields and file uploads */
if (!cgiWriteString(out, e->fileName)) {
goto error;
}
if (!cgiWriteString(out, e->contentType)) {
goto error;
}
if (!cgiWriteInt(out, e->valueLength)) {
goto error;
}
if (cgiFormFileOpen(e->attr, &fp) == cgiFormSuccess) {
char buffer[1024];
int got;
if (!cgiWriteInt(out, 1)) {
cgiFormFileClose(fp);
goto error;
}
while (cgiFormFileRead(fp, buffer,
sizeof(buffer), &got) == cgiFormSuccess)
{
if (((int) fwrite(buffer, 1, got, out)) != got) {
cgiFormFileClose(fp);
goto error;
}
}
if (cgiFormFileClose(fp) != cgiFormSuccess) {
goto error;
}
} else {
if (!cgiWriteInt(out, 0)) {
goto error;
}
}
e = e->next;
}
fclose(out);
return cgiEnvironmentSuccess;
error:
fclose(out);
/* If this function is not defined in your system,
you must substitute the appropriate
file-deletion function. */
unlink(filename);
return cgiEnvironmentIO;
}
static int cgiWriteString(FILE *out, char *s) {
int len = (int) strlen(s);
cgiWriteInt(out, len);
if (((int) fwrite(s, 1, len, out)) != len) {
return 0;
}
return 1;
}
static int cgiWriteInt(FILE *out, int i) {
if (!fwrite(&i, sizeof(int), 1, out)) {
return 0;
}
return 1;
}
static int cgiReadString(FILE *out, char **s);
static int cgiReadInt(FILE *out, int *i);
cgiEnvironmentResultType cgiReadEnvironment(char *filename) {
FILE *in;
cgiFormEntry *e = 0, *p;
char *version;
/* Prevent compiler warnings */
cgiEnvironmentResultType result = cgiEnvironmentIO;
/* Free any existing data first */
cgiFreeResources();
/* Be sure to open in binary mode */
in = fopen(filename, "rb");
if (!in) {
/* Can't access file */
return cgiEnvironmentIO;
}
if (!cgiReadString(in, &version)) {
goto error;
}
if (strcmp(version, "CGIC" CGIC_VERSION)) {
/* 2.02: Merezko Oleg */
free(version);
return cgiEnvironmentWrongVersion;
}
/* 2.02: Merezko Oleg */
free(version);
if (!cgiReadString(in, &cgiServerSoftware)) {
goto error;
}
if (!cgiReadString(in, &cgiServerName)) {
goto error;
}
if (!cgiReadString(in, &cgiGatewayInterface)) {
goto error;
}
if (!cgiReadString(in, &cgiServerProtocol)) {
goto error;
}
if (!cgiReadString(in, &cgiServerPort)) {
goto error;
}
if (!cgiReadString(in, &cgiRequestMethod)) {
goto error;
}
if (!cgiReadString(in, &cgiPathInfo)) {
goto error;
}
if (!cgiReadString(in, &cgiPathTranslated)) {
goto error;
}
if (!cgiReadString(in, &cgiScriptName)) {
goto error;
}
if (!cgiReadString(in, &cgiQueryString)) {
goto error;
}
if (!cgiReadString(in, &cgiRemoteHost)) {
goto error;
}
if (!cgiReadString(in, &cgiRemoteAddr)) {
goto error;
}
if (!cgiReadString(in, &cgiAuthType)) {
goto error;
}
if (!cgiReadString(in, &cgiRemoteUser)) {
goto error;
}
if (!cgiReadString(in, &cgiRemoteIdent)) {
goto error;
}
if (!cgiReadString(in, &cgiContentType)) {
goto error;
}
if (!cgiReadString(in, &cgiAccept)) {
goto error;
}
if (!cgiReadString(in, &cgiUserAgent)) {
goto error;
}
if (!cgiReadString(in, &cgiReferrer)) {
goto error;
}
/* 2.0 */
if (!cgiReadString(in, &cgiCookie)) {
goto error;
}
if (!cgiReadInt(in, &cgiContentLength)) {
goto error;
}
p = 0;
while (1) {
int fileFlag;
e = (cgiFormEntry *) calloc(1, sizeof(cgiFormEntry));
if (!e) {
cgiFreeResources();
fclose(in);
return cgiEnvironmentMemory;
}
memset(e, 0, sizeof(cgiFormEntry));
if (!cgiReadString(in, &e->attr)) {
/* This means we've reached the end of the list. */
/* 2.02: thanks to Merezko Oleg */
free(e);
break;
}
if (!cgiReadString(in, &e->value)) {
goto outOfMemory;
}
if (!cgiReadString(in, &e->fileName)) {
goto outOfMemory;
}
if (!cgiReadString(in, &e->contentType)) {
goto outOfMemory;
}
if (!cgiReadInt(in, &e->valueLength)) {
goto outOfMemory;
}
if (!cgiReadInt(in, &fileFlag)) {
goto outOfMemory;
}
if (fileFlag) {
char buffer[1024];
FILE *out;
char tfileName[1024];
int got;
int len = e->valueLength;
if (getTempFileName(tfileName)
!= cgiParseSuccess)
{
result = cgiEnvironmentIO;
goto error;
}
out = fopen(tfileName, "w+b");
if (!out) {
result = cgiEnvironmentIO;
goto error;
}
while (len > 0) {
/* 2.01: try is a bad variable name in
C++, and it wasn't being used
properly either */
int tryr = len;
if (tryr > ((int) sizeof(buffer))) {
tryr = sizeof(buffer);
}
got = fread(buffer, 1, tryr, in);
if (got <= 0) {
result = cgiEnvironmentIO;
fclose(out);
unlink(tfileName);
goto error;
}
if (((int) fwrite(buffer, 1, got, out)) != got) {
result = cgiEnvironmentIO;
fclose(out);
unlink(tfileName);
goto error;
}
len -= got;
}
/* cgic 2.05: should be fclose not rewind */
fclose(out);
e->tfileName = (char *) malloc((int) strlen(tfileName) + 1);
if (!e->tfileName) {
result = cgiEnvironmentMemory;
unlink(tfileName);
goto error;
}
strcpy(e->tfileName, tfileName);
} else {
e->tfileName = (char *) malloc(1);
if (!e->tfileName) {
result = cgiEnvironmentMemory;
goto error;
}
}
e->next = 0;
if (p) {
p->next = e;
} else {
cgiFormEntryFirst = e;
}
p = e;
}
fclose(in);
cgiRestored = 1;
return cgiEnvironmentSuccess;
outOfMemory:
result = cgiEnvironmentMemory;
error:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -