⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cgic.c

📁 超级搜索动感版v2.0 - 源码下载常用软件下fastcgi库.cnv2.0 版主要更新: 1、界面更友善 2、优化主代码 3、更新热门词 4、增加搜索排行榜 5、
💻 C
📖 第 1 页 / 共 4 页
字号:
/* cgicTempDir is the only setting you are likely to need	to change in this file. *//* Used only in Unix environments, in conjunction with mkstemp(). 	Elsewhere (Windows), temporary files go where the tmpnam() 	function suggests. If this behavior does not work for you, 	modify the getTempFileName() function to suit your needs. */#define cgicTempDir "/tmp"#if CGICDEBUG#define CGICDEBUGSTART \	{ \		FILE *dout; \		dout = fopen("/home/boutell/public_html/debug", "a"); \	#define CGICDEBUGEND \		fclose(dout); \	}#else /* CGICDEBUG */#define CGICDEBUGSTART#define CGICDEBUGEND#endif /* CGICDEBUG */#include <stdio.h>#include <string.h>#include <ctype.h>#include <stdlib.h>#include <time.h>#include <sys/types.h>#include <sys/stat.h>#ifdef WIN32#include <io.h>/* cgic 2.01 */#include <fcntl.h>#else#include <unistd.h>#endif /* WIN32 */#include "cgic.h"#define cgiStrEq(a, b) (!strcmp((a), (b)))char *cgiServerSoftware;char *cgiServerName;char *cgiGatewayInterface;char *cgiServerProtocol;char *cgiServerPort;char *cgiRequestMethod;char *cgiPathInfo;char *cgiPathTranslated;char *cgiScriptName;char *cgiQueryString;char *cgiRemoteHost;char *cgiRemoteAddr;char *cgiAuthType;char *cgiRemoteUser;char *cgiRemoteIdent;char cgiContentTypeData[1024];char *cgiContentType = cgiContentTypeData;char *cgiMultipartBoundary;char *cgiCookie;int cgiContentLength;char *cgiAccept;char *cgiUserAgent;char *cgiReferrer;FILE *cgiIn;FILE *cgiOut;/* True if CGI environment was restored from a file. */static int cgiRestored = 0;static void cgiGetenv(char **s, char *var);typedef enum {	cgiParseSuccess,	cgiParseMemory,	cgiParseIO} cgiParseResultType;/* One form entry, consisting of an attribute-value pair,	and an optional filename and content type. All of	these are guaranteed to be valid null-terminated strings,	which will be of length zero in the event that the	field is not present, with the exception of tfileName	which will be null when 'in' is null. DO NOT MODIFY THESE 	VALUES. Make local copies if modifications are desired. */typedef struct cgiFormEntryStruct {        char *attr;	/* value is populated for regular form fields only.		For file uploads, it points to an empty string, and file		upload data should be read from the file tfileName. */ 	char *value;	/* When fileName is not an empty string, tfileName is not null,		and 'value' points to an empty string. */	/* Valid for both files and regular fields; does not include		terminating null of regular fields. */	int valueLength;	char *fileName;		char *contentType;	/* Temporary file name for working storage of file uploads. */	char *tfileName;        struct cgiFormEntryStruct *next;} cgiFormEntry;/* The first form entry. */static cgiFormEntry *cgiFormEntryFirst;static cgiParseResultType cgiParseGetFormInput();static cgiParseResultType cgiParsePostFormInput();static cgiParseResultType cgiParsePostMultipartInput();static cgiParseResultType cgiParseFormInput(char *data, int length);static void cgiSetupConstants();static void cgiFreeResources();static int cgiStrEqNc(char *s1, char *s2);static int cgiStrBeginsNc(char *s1, char *s2);int main(int argc, char *argv[]) {	int result;	char *cgiContentLengthString;	char *e;	cgiSetupConstants();	cgiGetenv(&cgiServerSoftware, "SERVER_SOFTWARE");	cgiGetenv(&cgiServerName, "SERVER_NAME");	cgiGetenv(&cgiGatewayInterface, "GATEWAY_INTERFACE");	cgiGetenv(&cgiServerProtocol, "SERVER_PROTOCOL");	cgiGetenv(&cgiServerPort, "SERVER_PORT");	cgiGetenv(&cgiRequestMethod, "REQUEST_METHOD");	cgiGetenv(&cgiPathInfo, "PATH_INFO");	cgiGetenv(&cgiPathTranslated, "PATH_TRANSLATED");	cgiGetenv(&cgiScriptName, "SCRIPT_NAME");	cgiGetenv(&cgiQueryString, "QUERY_STRING");	cgiGetenv(&cgiRemoteHost, "REMOTE_HOST");	cgiGetenv(&cgiRemoteAddr, "REMOTE_ADDR");	cgiGetenv(&cgiAuthType, "AUTH_TYPE");	cgiGetenv(&cgiRemoteUser, "REMOTE_USER");	cgiGetenv(&cgiRemoteIdent, "REMOTE_IDENT");	/* 2.0: the content type string needs to be parsed and modified, so		copy it to a buffer. */	e = getenv("CONTENT_TYPE");	if (e) {		if (strlen(e) < sizeof(cgiContentTypeData)) {			strcpy(cgiContentType, e);		} else {			/* Truncate safely in the event of what is almost certainly				a hack attempt */			strncpy(cgiContentType, e, sizeof(cgiContentTypeData));			cgiContentType[sizeof(cgiContentTypeData) - 1] = '\0';		}	} else {		cgiContentType[0] = '\0';	}	/* Never null */	cgiMultipartBoundary = "";	/* 2.0: parse semicolon-separated additional parameters of the		content type. The one we're interested in is 'boundary'.		We discard the rest to make cgiContentType more useful		to the typical programmer. */	if (strchr(cgiContentType, ';')) {		char *sat = strchr(cgiContentType, ';');		while (sat) {			*sat = '\0';			sat++;			while (isspace(*sat)) {				sat++;			}				if (cgiStrBeginsNc(sat, "boundary=")) {				char *s;				cgiMultipartBoundary = sat + strlen("boundary=");				s = cgiMultipartBoundary;				while ((*s) && (!isspace(*s))) {					s++;				}				*s = '\0';				break;			} else {				sat = strchr(sat, ';');			} 			}	}	cgiGetenv(&cgiContentLengthString, "CONTENT_LENGTH");	cgiContentLength = atoi(cgiContentLengthString);		cgiGetenv(&cgiAccept, "HTTP_ACCEPT");	cgiGetenv(&cgiUserAgent, "HTTP_USER_AGENT");	cgiGetenv(&cgiReferrer, "HTTP_REFERER");	cgiGetenv(&cgiCookie, "HTTP_COOKIE");#ifdef CGICDEBUG	CGICDEBUGSTART	fprintf(dout, "%d\n", cgiContentLength);	fprintf(dout, "%s\n", cgiRequestMethod);	fprintf(dout, "%s\n", cgiContentType);	CGICDEBUGEND	#endif /* CGICDEBUG */#ifdef WIN32	/* 1.07: Must set stdin and stdout to binary mode */	/* 2.0: this is particularly crucial now and must not be removed */	_setmode( _fileno( stdin ), _O_BINARY );	_setmode( _fileno( stdout ), _O_BINARY );#endif /* WIN32 */	cgiFormEntryFirst = 0;	cgiIn = stdin;	cgiOut = stdout;	cgiRestored = 0;	/* These five lines keep compilers from		producing warnings that argc and argv		are unused. They have no actual function. */	if (argc) {		if (argv[0]) {			cgiRestored = 0;		}	}		if (cgiStrEqNc(cgiRequestMethod, "post")) {#ifdef CGICDEBUG		CGICDEBUGSTART		fprintf(dout, "POST recognized\n");		CGICDEBUGEND#endif /* CGICDEBUG */		if (cgiStrEqNc(cgiContentType, "application/x-www-form-urlencoded")) {	#ifdef CGICDEBUG			CGICDEBUGSTART			fprintf(dout, "Calling PostFormInput\n");			CGICDEBUGEND	#endif /* CGICDEBUG */			if (cgiParsePostFormInput() != cgiParseSuccess) {#ifdef CGICDEBUG				CGICDEBUGSTART				fprintf(dout, "PostFormInput failed\n");				CGICDEBUGEND	#endif /* CGICDEBUG */				cgiFreeResources();				return -1;			}	#ifdef CGICDEBUG			CGICDEBUGSTART			fprintf(dout, "PostFormInput succeeded\n");			CGICDEBUGEND	#endif /* CGICDEBUG */		} else if (cgiStrEqNc(cgiContentType, "multipart/form-data")) {#ifdef CGICDEBUG			CGICDEBUGSTART			fprintf(dout, "Calling PostMultipartInput\n");			CGICDEBUGEND	#endif /* CGICDEBUG */			if (cgiParsePostMultipartInput() != cgiParseSuccess) {#ifdef CGICDEBUG				CGICDEBUGSTART				fprintf(dout, "PostMultipartInput failed\n");				CGICDEBUGEND	#endif /* CGICDEBUG */				cgiFreeResources();				return -1;			}	#ifdef CGICDEBUG			CGICDEBUGSTART			fprintf(dout, "PostMultipartInput succeeded\n");			CGICDEBUGEND	#endif /* CGICDEBUG */		}	} else if (cgiStrEqNc(cgiRequestMethod, "get")) {			/* The spec says this should be taken care of by			the server, but... it isn't */		cgiContentLength = strlen(cgiQueryString);		if (cgiParseGetFormInput() != cgiParseSuccess) {#ifdef CGICDEBUG			CGICDEBUGSTART			fprintf(dout, "GetFormInput failed\n");			CGICDEBUGEND	#endif /* CGICDEBUG */			cgiFreeResources();			return -1;		} else {	#ifdef CGICDEBUG			CGICDEBUGSTART			fprintf(dout, "GetFormInput succeeded\n");			CGICDEBUGEND	#endif /* CGICDEBUG */		}	}	result = cgiMain();	cgiFreeResources();	return result;}static void cgiGetenv(char **s, char *var){	*s = getenv(var);	if (!(*s)) {		*s = "";	}}static cgiParseResultType cgiParsePostFormInput() {	char *input;	cgiParseResultType result;	if (!cgiContentLength) {		return cgiParseSuccess;	}	input = (char *) malloc(cgiContentLength);	if (!input) {		return cgiParseMemory;		}	if (((int) fread(input, 1, cgiContentLength, cgiIn)) 		!= cgiContentLength) 	{		return cgiParseIO;	}		result = cgiParseFormInput(input, cgiContentLength);	free(input);	return result;}/* 2.0: A virtual datastream supporting putback of 	enough characters to handle multipart boundaries easily.	A simple memset(&mp, 0, sizeof(mp)) is suitable initialization. */typedef struct {	/* Buffer for putting characters back */	char putback[1024];		/* Position in putback from which next character will be read.		If readPos == writePos, then next character should		come from cgiIn. */	int readPos;	/* Position in putback to which next character will be put back.		If writePos catches up to readPos, as opposed to the other		way around, the stream no longer functions properly.		Calling code must guarantee that no more than 		sizeof(putback) bytes are put back at any given time. */	int writePos;	/* Offset in the virtual datastream; can be compared		to cgiContentLength */	int offset;} mpStream, *mpStreamPtr;int mpRead(mpStreamPtr mpp, char *buffer, int len){	int ilen = len;	int got = 0;	while (len) {		if (mpp->readPos != mpp->writePos) {			*buffer++ = mpp->putback[mpp->readPos++];			mpp->readPos %= sizeof(mpp->putback);			got++;			len--;		} else {			break;		}		}	/* Refuse to read past the declared length in order to		avoid deadlock */	if (len > (cgiContentLength - mpp->offset)) {		len = cgiContentLength - mpp->offset;	}	if (len) {		int fgot = fread(buffer, 1, len, cgiIn);		if (fgot >= 0) {			mpp->offset += (got + fgot);			return got + fgot;		} else if (got > 0) {			mpp->offset += got;			return got;		} else {			/* EOF or error */			return fgot;		}	} else if (got) {		return got;	} else if (ilen) {			return EOF;	} else {		/* 2.01 */		return 0;	}}void mpPutBack(mpStreamPtr mpp, char *data, int len){	mpp->offset -= len;	while (len) {		mpp->putback[mpp->writePos++] = *data++;		mpp->writePos %= sizeof(mpp->putback);		len--;	}}/* This function copies the body to outf if it is not null, otherwise to	a newly allocated character buffer at *outP, which will be null	terminated; if both outf and outP are null the body is not stored.	If bodyLengthP is not null, the size of the body in bytes is stored	to *bodyLengthP, not including any terminating null added to *outP. 	If 'first' is nonzero, a preceding newline is not expected before	the boundary. If 'first' is zero, a preceding newline is expected.	Upon return mpp is positioned after the boundary and its trailing 	newline, if any; if the boundary is followed by -- the next two 	characters read after this function returns will be --. Upon error, 	if outP is not null, *outP is a null pointer; *bodyLengthP 	is set to zero. Returns cgiParseSuccess, cgiParseMemory 	or cgiParseIO. */static cgiParseResultType afterNextBoundary(mpStreamPtr mpp,	FILE *outf,	char **outP,	int *bodyLengthP,	int first	);static int readHeaderLine(	mpStreamPtr mpp,		char *attr,	int attrSpace,	char *value,	int valueSpace);static void decomposeValue(char *value,	char *mvalue, int mvalueSpace,	char **argNames,	char **argValues,	int argValueSpace);/* tfileName must be 1024 bytes to ensure adequacy on	win32 (1024 exceeds the maximum path length and	certainly exceeds observed behavior of _tmpnam).	May as well also be 1024 bytes on Unix, although actual	length is strlen(cgiTempDir) + a short unique pattern. */	static cgiParseResultType getTempFileName(char *tfileName);static cgiParseResultType cgiParsePostMultipartInput() {	cgiParseResultType result;	cgiFormEntry *n = 0, *l = 0;	int got;	FILE *outf = 0;	char *out = 0;	char tfileName[1024];	mpStream mp;	mpStreamPtr mpp = &mp;	memset(&mp, 0, sizeof(mp));	if (!cgiContentLength) {		return cgiParseSuccess;	}	/* Read first boundary, including trailing newline */	result = afterNextBoundary(mpp, 0, 0, 0, 1);	if (result == cgiParseIO) {			/* An empty submission is not necessarily an error */		return cgiParseSuccess;	} else if (result != cgiParseSuccess) {		return result;	}	while (1) {		char d[1024];		char fvalue[1024];		char fname[1024];		int bodyLength = 0;		char ffileName[1024];		char fcontentType[1024];		char attr[1024];		char value[1024];		fvalue[0] = 0;		fname[0] = 0;		ffileName[0] = 0;		fcontentType[0] = 0;		out = 0;		outf = 0;		/* Check for EOF */		got = mpRead(mpp, d, 2);		if (got < 2) {			/* Crude EOF */			break;		}		if ((d[0] == '-') && (d[1] == '-')) {			/* Graceful EOF */			break;		}		mpPutBack(mpp, d, 2);		/* Read header lines until end of header */		while (readHeaderLine(				mpp, attr, sizeof(attr), value, sizeof(value))) 		{			char *argNames[3];			char *argValues[2];			/* Content-Disposition: form-data; 				name="test"; filename="googley.gif" */			if (cgiStrEqNc(attr, "Content-Disposition")) {				argNames[0] = "name";				argNames[1] = "filename";				argNames[2] = 0;				argValues[0] = fname;				argValues[1] = ffileName;				decomposeValue(value, 					fvalue, sizeof(fvalue),					argNames,					argValues,					1024);				} else if (cgiStrEqNc(attr, "Content-Type")) {				argNames[0] = 0;				decomposeValue(value, 					fcontentType, sizeof(fcontentType),					argNames,					0,					0);			}		}		if (!cgiStrEqNc(fvalue, "form-data")) {			/* Not form data */				continue;		}		/* Body is everything from here until the next 			boundary. So, set it aside and move past boundary. 			If a filename was submitted as part of the			disposition header, store to a temporary file.			Otherwise, store to a memory buffer (it is			presumably a regular form field). */		if (strlen(ffileName)) {			if (getTempFileName(tfileName) != cgiParseSuccess) {				return cgiParseIO;			}				outf = fopen(tfileName, "w+b");		} else {			outf = 0;			tfileName[0] = '\0';		}			result = afterNextBoundary(mpp, outf, &out, &bodyLength, 0);		if (result != cgiParseSuccess) {			/* Lack of a boundary here is an error. */			if (outf) {				fclose(outf);				unlink(tfileName);			}			if (out) {				free(out);			}			return result;		}		/* OK, we have a new pair, add it to the list. */		n = (cgiFormEntry *) malloc(sizeof(cgiFormEntry));			if (!n) {			goto outOfMemory;		}		memset(n, 0, sizeof(cgiFormEntry));		/* 2.01: one of numerous new casts required			to please C++ compilers */		n->attr = (char *) malloc(strlen(fname) + 1);		if (!n->attr) {			goto outOfMemory;		}		strcpy(n->attr, fname);		if (out) {			n->value = out;			out = 0;		} else if (outf) {			n->value = (char *) malloc(1);			if (!n->value) {				goto outOfMemory;			}			n->value[0] = '\0';			fclose(outf);		}		n->valueLength = bodyLength;		n->next = 0;		if (!l) {			cgiFormEntryFirst = n;		} else {			l->next = n;		}		n->fileName = (char *) malloc(strlen(ffileName) + 1);		if (!n->fileName) {			goto outOfMemory;		}		strcpy(n->fileName, ffileName);		n->contentType = (char *) malloc(strlen(fcontentType) + 1);		if (!n->contentType) {			goto outOfMemory;		}		strcpy(n->contentType, fcontentType);		n->tfileName = (char *) malloc(strlen(tfileName) + 1);		if (!n->tfileName) {			goto outOfMemory;		}		strcpy(n->tfileName, tfileName);		l = n;				}		return cgiParseSuccess;outOfMemory:	if (n) {		if (n->attr) {			free(n->attr);		}		if (n->value) {			free(n->value);		}		if (n->fileName) {			free(n->fileName);		}		if (n->tfileName) {			free(n->tfileName);		}		if (n->contentType) {			free(n->contentType);		}		free(n);	}	if (out) {		free(out);	}	if (outf) {		fclose(outf);		unlink(tfileName);	}	return cgiParseMemory;}static cgiParseResultType getTempFileName(char *tfileName){#ifndef WIN32	/* Unix. Use the robust 'mkstemp' function to create		a temporary file that is truly unique, with		permissions that are truly safe. The 		fopen-for-write destroys any bogus information		written by potential hackers during the brief		window between the file's creation and the		chmod call (glibc 2.0.6 and lower might		otherwise have allowed this). */	int outfd; 	strcpy(tfileName, cgicTempDir "/cgicXXXXXX");	outfd = mkstemp(tfileName);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -