📄 cgi.c
字号:
/* 4567890123456789012345678901234567890123456789012345678901234567890123456789
**
** File cgi.c
**
** Desc A CGI library for C programmers. Automatically handles GET, POST
** and ISINDEX requests, with lots of useful routines to simplify
** CGI development. Applications can even be debugged from the
** commandline!
**
** Usage See http://www.jemtek.com.au/jemtek/cgi/lib
**
** Limits Cannot yet handle form file uploads.
**
** Copyright 1996 JemTek Pty Ltd, Jerome Munchenberg
** http://www.jemtek.com.au/jemtek
** jerome@jemtek.com.au
**
** History Ver Date Author Modification
** 1.0 06-03-96 JEM First Draft
** 1.1 29-07-96 JEM Modified error messages in main
** 31-08-96 JEM Swapped LFs for NLs in http headers
** 1.2 06-12-96 JEM Fixed ambiguous pointers in cgiDecodeUrl
** 1.3 11-02-97 JEM Created cgiStrdup to replace non-ansi strdup
**
******************************************************************************/
/* Includes
******************************************************************************/
#include <stdio.h>
#include <stdlib.h> /* getenv */
#include <stdarg.h> /* vfprintf */
#include <string.h> /* str... */
#include <ctype.h> /* is... */
#include "cgi.h"
/* Local global variables
******************************************************************************/
static int cgiHeaderFlag = 0;
static int cgiHtmlFlag = 0;
static int cgiArgc = 0;
static char **cgiArgv = NULL;
static char *cgiStdin = NULL;
typedef struct {
char *var;
char *val;
} pair_t;
typedef struct {
int size;
pair_t *pair;
} form_t;
form_t form;
/* Local function declaration
******************************************************************************/
static char *cgiStrdup(char *s);
static char *cgiDebugGetStr(FILE *fp);
static int cgiDebugGetInt(FILE *fp);
static int cgiDebugEnvLoad(char *file);
static int cgiDebugEnvSave(char *file);
static char *cgiDecodeUrl(char *data);
static int cgiFormAdd(char *var, char *val);
static char *cgiGetEnv(char *var);
static char *cgiGetStdin(int len);
static char cgiHexAsc(char x1, char x2);
static int cgiHexInt(char x);
static int cgiParseArgs(char **argv, int argc);
static int cgiParseInput(char *input, int len);
/* Library functions
******************************************************************************/
/******************************************************************************
**
** Function cgiDisplayEnv
**
** Purpose Display CGI specific environment variables stored in cgiEnv struc
**
** History Date Author Modification
** 04-03-96 JEM First Draft
**
******************************************************************************/
void cgiDisplayEnv(void)
{
if (!cgiHeaderFlag)
return;
cgiPrintf("<H2>CGI Global Structure</H2>");
cgiPrintf("<PRE>");
cgiPrintf("%-23s [%s]", "cgiEnv.authType", cgiEnv.authType);
cgiPrintf("%-23s [%i]", "cgiEnv.contentLength", cgiEnv.contentLength);
cgiPrintf("%-23s [%s]", "cgiEnv.contentType", cgiEnv.contentType);
cgiPrintf("%-23s [%s]", "cgiEnv.gatewayInterface", cgiEnv.gatewayInterface);
cgiPrintf("%-23s [%s]", "cgiEnv.httpAccept", cgiEnv.httpAccept);
cgiPrintf("%-23s [%s]", "cgiEnv.httpHost", cgiEnv.httpHost);
cgiPrintf("%-23s [%s]", "cgiEnv.httpReferer", cgiEnv.httpReferer);
cgiPrintf("%-23s [%s]", "cgiEnv.httpUserAgent", cgiEnv.httpUserAgent);
cgiPrintf("%-23s [%s]", "cgiEnv.pathInfo", cgiEnv.pathInfo);
cgiPrintf("%-23s [%s]", "cgiEnv.pathTranslated", cgiEnv.pathTranslated);
cgiPrintf("%-23s [%s]", "cgiEnv.queryString", cgiEnv.queryString);
cgiPrintf("%-23s [%s]", "cgiEnv.remoteAddr", cgiEnv.remoteAddr);
cgiPrintf("%-23s [%s]", "cgiEnv.remoteHost", cgiEnv.remoteHost);
cgiPrintf("%-23s [%s]", "cgiEnv.remoteIdent", cgiEnv.remoteIdent);
cgiPrintf("%-23s [%s]", "cgiEnv.remoteUser", cgiEnv.remoteUser);
cgiPrintf("%-23s [%s]", "cgiEnv.requestMethod", cgiEnv.requestMethod);
cgiPrintf("%-23s [%s]", "cgiEnv.scriptName", cgiEnv.scriptName);
cgiPrintf("%-23s [%s]", "cgiEnv.serverName", cgiEnv.serverName);
cgiPrintf("%-23s [%s]", "cgiEnv.serverPort", cgiEnv.serverPort);
cgiPrintf("%-23s [%s]", "cgiEnv.serverProtocol", cgiEnv.serverProtocol);
cgiPrintf("%-23s [%s]", "cgiEnv.serverSoftware", cgiEnv.serverSoftware);
cgiPrintf("</PRE>");
}
/******************************************************************************
**
** Function cgiDisplayPairs
**
** Purpose Display var=val pairs from form
**
** History Date Author Modification
** 06-03-96 JEM First Draft
**
******************************************************************************/
void cgiDisplayPairs()
{
int cnt;
if (!cgiHeaderFlag)
return;
cgiPrintf("<H2>Form Pairs</H2>");
cgiPrintf("<PRE>");
if(!form.size)
cgiPrintf("(no data)");
else
for(cnt=0; cnt<form.size; cnt++)
cgiPrintf("%2i %-12s [%s]", cnt, form.pair[cnt].var, form.pair[cnt].val);
cgiPrintf("</PRE>");
}
/******************************************************************************
**
** Function cgiEncodeSys
**
** Purpose Escape shell metacharacters in a string (for calls to popen etc)
**
** History Date Author Modification
** 15-03-96 JEM First Draft
**
******************************************************************************/
char *cgiEncodeSys(char *data)
{
char *i, *j, *code;
int inc;
for (inc=0, i=data; *i!='\0'; i++)
if (strchr("&;`'|*?~<>^()[]{}$\"\n\\", *i))
++inc;
if (!(code = (char*)malloc(strlen(data)+inc+1)))
return NULL;
for (j=code, i=data; *i!='\0'; i++, j++)
{
if (strchr("&;`'|*?~<>^()[]{}$\"\n\\", *i))
*j++ = '\\';
*j = *i;
}
*j = '\0';
return code;
}
/******************************************************************************
**
** Function cgiEncodeUrl
**
** Purpose URL-encode a string (Convert space to plus, non-ascii to hex)
**
** History Date Author Modification
** 08-03-96 JEM First Draft
**
******************************************************************************/
char *cgiEncodeUrl(char *data)
{
char *hex = "0123456789ABCDEF";
char *i, *j, *code;
int inc;
for (inc=0, i=data; *i!='\0'; i++)
if (!isalnum(*i))
inc += 2;
if (!(code = (char*)malloc(strlen(data)+inc+1)))
return NULL;
for (j=code, i=data; *i!='\0'; i++, j++)
{
if (*i == ' ')
*j = '+';
else
if (!isalnum(*i))
{
*j++ = '%';
*j++ = hex[*i/16];
*j = hex[*i%16];
}
else
*j = *i;
}
*j = '\0';
return code;
}
/******************************************************************************
**
** Function cgiFormCmpVal
**
** Purpose Compares the value of a variable with another value
**
** History Date Author Modification
** 18-03-96 JEM First Draft
**
******************************************************************************/
int cgiFormCmpVal(char *var, char *val)
{
char **vals;
int cnt, len;
len = cgiFormGetValMulti(var, &vals);
for (cnt=0; cnt<len; cnt++)
if (!strcmp(val, vals[cnt]))
return 1;
return 0;
}
/******************************************************************************
**
** Function cgiFormCmpValMulti
**
** Purpose Compares the value of a variable with an array of values
**
** History Date Author Modification
** 18-03-96 JEM First Draft
**
******************************************************************************/
int cgiFormCmpValMulti(char *var, char len, char **vals)
{
char **fvals;
int cnt, fcnt, flen;
flen = cgiFormGetValMulti(var, &fvals);
for (fcnt=0; fcnt<flen; fcnt++)
for (cnt=0; cnt<len; cnt++)
if (!strcmp(vals[cnt], fvals[fcnt]))
return 1;
return 0;
}
/******************************************************************************
**
** Function cgiFormCntVar
**
** Purpose Test for a variable
**
** History Date Author Modification
** 04-03-96 JEM First Draft
**
******************************************************************************/
int cgiFormCntVar(char *var)
{
int cnt, len;
for(len=cnt=0; cnt<form.size; cnt++)
if (!strcmp(var, form.pair[cnt].var))
++len;
return len;
}
/******************************************************************************
**
** Function cgiFormGetVal
**
** Purpose Return the value of the given variable
**
** History Date Author Modification
** 04-03-96 JEM First Draft
**
******************************************************************************/
char *cgiFormGetVal(char *var)
{
int cnt;
for(cnt=0; cnt<form.size; cnt++)
if (!strcmp(var, form.pair[cnt].var))
return cgiStrdup(form.pair[cnt].val);
return NULL;
}
/******************************************************************************
**
** Function cgiFormGetValMulti
**
** Purpose Return multiple values of the given variable
**
** History Date Author Modification
** 04-03-96 JEM First Draft
**
******************************************************************************/
int cgiFormGetValMulti(char *var, char ***vals)
{
int len, cnt;
*vals = NULL;
for(len=cnt=0; cnt<form.size; cnt++)
if (!strcmp(var, form.pair[cnt].var))
{
if (!(*vals = (char**)realloc(*vals, (len+1)*sizeof(char*))))
return 0;
if (!((*vals)[len++] = cgiStrdup(form.pair[cnt].val)))
return 0;
}
return len;
}
/******************************************************************************
**
** Function cgiHeaderContent
**
** Purpose Indicate the MIME type of the document
**
** History Date Author Modification
** 04-03-96 JEM First Draft
**
******************************************************************************/
int cgiHeaderContent(char *mimeType)
{
if (cgiHeaderFlag++)
return 0;
printf("Content-Type: %s\n\n", mimeType);
return 1;
}
/******************************************************************************
**
** Function cgiHeaderLocation
**
** Purpose Redirect the browser to a new resource
**
** History Date Author Modification
** 04-03-96 JEM First Draft
**
******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -