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

📄 cgi.c

📁 goahead,一个非常好用的web服务器,支持html和cgi,可以运行在多个平台之上.
💻 C
📖 第 1 页 / 共 5 页
字号:
		} 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);
	if (outfd == -1) {
		return cgiParseIO;
	}
	close(outfd);
	/* Fix the permissions */
	if (chmod(tfileName, 0600) != 0) {
		unlink(tfileName);
		return cgiParseIO;
	}
#else
	/* Non-Unix. Do what we can. */
	if (!tmpnam(tfileName)) {
		return cgiParseIO;
	}
#endif
	return cgiParseSuccess;
}


#define APPEND(string, char) \
	{ \
		if ((string##Len + 1) < string##Space) { \
			string[string##Len++] = (char); \
		} \
	}

#define RAPPEND(string, ch) \
	{ \
		if ((string##Len + 1) == string##Space)  { \
			char *sold = string; \
			string##Space *= 2; \
			string = (char *) realloc(string, string##Space); \
			if (!string) { \
				string = sold; \
				goto outOfMemory; \
			} \
		} \
		string[string##Len++] = (ch); \
	}
		
#define BAPPEND(ch) \
	{ \
		if (outf) { \
			putc(ch, outf); \
			outLen++; \
		} else if (out) { \
			RAPPEND(out, ch); \
		} \
	}

cgiParseResultType afterNextBoundary(mpStreamPtr mpp, FILE *outf, char **outP,
	int *bodyLengthP, int first)
{
	int outLen = 0;
	int outSpace = 256;
	char *out = 0;
	cgiParseResultType result;
	int boffset;
	int got;
	char d[2];	
	/* This is large enough, because the buffer into which the
		original boundary string is fetched is shorter by more
		than four characters due to the space required for
		the attribute name */
	char workingBoundaryData[1024];
	char *workingBoundary = workingBoundaryData;
	int workingBoundaryLength;
	if ((!outf) && (outP)) {
		out = (char *) malloc(outSpace);
		if (!out) {
			goto outOfMemory;
		}
	}
	boffset = 0;
	sprintf(workingBoundaryData, "\r\n--%s", cgiMultipartBoundary);
	if (first) {
		workingBoundary = workingBoundaryData + 2;
	}
	workingBoundaryLength = strlen(workingBoundary);
	while (1) {
		got = mpRead(mpp, d, 1);
		if (got != 1) {
			/* 2.01: cgiParseIO, not cgiFormIO */
			result = cgiParseIO;
			goto error;
		}
		if (d[0] == workingBoundary[boffset]) {
			/* We matched the next byte of the boundary.
				Keep track of our progress into the
				boundary and don't emit anything. */
			boffset++;
			if (boffset == workingBoundaryLength) {
				break;
			} 
		} else if (boffset > 0) {
			/* We matched part, but not all, of the
				boundary. Now we have to be careful:
				put back all except the first
				character and try again. The 
				real boundary could begin in the
				middle of a false match. We can
				emit the first character only so far. */
			BAPPEND(workingBoundary[0]);
			mpPutBack(mpp, 
				workingBoundary + 1, boffset - 1);
			mpPutBack(mpp, d, 1);
			boffset = 0;
		} else {		
			/* Not presently in the middle of a boundary
				match; just emit the character. */
			BAPPEND(d[0]);
		}	
	}
	/* Read trailing newline or -- EOF marker. A literal EOF here
		would be an error in the input stream. */
	got = mpRead(mpp, d, 2);
	if (got != 2) {
		result = cgiParseIO;
		goto error;
	}	
	if ((d[0] == '\r') && (d[1] == '\n')) {
		/* OK, EOL */
	} else if (d[0] == '-') {
		/* Probably EOF, but we check for
			that later */
		mpPutBack(mpp, d, 2);
	}	
	if (out && outSpace) {
		char *oout = out;
		out[outLen] = '\0';
		out = (char *) realloc(out, outLen + 1);
		if (!out) {
			/* Surprising if it happens; and not fatal! We were
				just trying to give some space back. We can
				keep it if we have to. */
			out = oout;
		}
		*outP = out;
	}
	if (bodyLengthP) {
		*bodyLengthP = outLen;
	}
	return cgiParseSuccess;
outOfMemory:
	result = cgiParseMemory;
	if (outP) {
		if (out) {
			free(out);
		}
		*outP = '\0';	
	}
error:
	if (bodyLengthP) {
		*bodyLengthP = 0;
	}
	if (out) {
		free(out);
	}
	if (outP) {
		*outP = 0;	
	}
	return result;
}

static void decomposeValue(char *value,
	char *mvalue, int mvalueSpace,
	char **argNames,
	char **argValues,
	int argValueSpace)
{
	char argName[1024];
	int argNameSpace = sizeof(argName);
	int argNameLen = 0;
	int mvalueLen = 0;
	char *argValue;
	int argNum = 0;
	while (argNames[argNum]) {
		if (argValueSpace) {
			argValues[argNum][0] = '\0';
		}
		argNum++;
	}
	while (isspace(*value)) {
		value++;
	}
	/* Quoted mvalue */
	if (*value == '\"') {
		value++;
		while ((*value) && (*value != '\"')) {
			APPEND(mvalue, *value);
			value++;
		}
		while ((*value) && (*value != ';')) {
			value++;
		}
	} else {
		/* Unquoted mvalue */
		while ((*value) && (*value != ';')) {
			APPEND(mvalue, *value);
			value++;
		}	
	}	
	if (mvalueSpace) {
		mvalue[mvalueLen] = '\0';
	}
	while (*value == ';') {
		int argNum;
		int argValueLen = 0;
		/* Skip the ; between parameters */
		value++;
		/* Now skip leading whitespace */
		while ((*value) && (isspace(*value))) { 
			value++;
		}
		/* Now read the parameter name */
		argNameLen = 0;
		while ((*value) && (isalnum(*value))) {
			APPEND(argName, *value);
			value++;
		}
		if (argNameSpace) {
			argName[argNameLen] = '\0';
		}
		while ((*value) && isspace(*value)) {
			value++;
		}
		if (*value != '=') {
			/* Malformed line */
			return;	
		}
		value++;
		while ((*value) && isspace(*value)) {
			value++;
		}
		/* Find the parameter in the argument list, if present */
		argNum = 0;
		argValue = 0;
		while (argNames[argNum]) {
			if (cgiStrEqNc(argName, argNames[argNum])) {
				argValue = argValues[argNum];
				break;
			}
			argNum++;
		}		
		/* Finally, read the parameter value */
		if (*value == '\"') {
			value++;
			while ((*value) && (*value != '\"')) {
				if (argValue) {
					APPEND(argValue, *value);
				}
				value++;
			}
			while ((*value) && (*value != ';')) {
				value++;
			}
		} else {
			/* Unquoted value */
			while ((*value) && (*value != ';')) {
				if (argNames[argNum]) {
					APPEND(argValue, *value);
				}
				value++;
			}	
		}	
		if (argValueSpace) {
			argValue[argValueLen] = '\0';
		}
	}	 	
}

static int readHeaderLine(
	mpStreamPtr mpp,
	char *attr,
	int attrSpace,
	char *value,
	int valueSpace)
{	
	int attrLen = 0;
	int valueLen = 0;
	int valueFound = 0;
	while (1) {
		char d[1];
		int got = mpRead(mpp, d, 1);
		if (got != 1) {	
			return 0;
		}
		if (d[0] == '\r') {
			got = mpRead(mpp, d, 1);
			if (got == 1) {	
				if (d[0] == '\n') {
					/* OK */
				} else {
					mpPutBack(mpp, d, 1);
				}
			}
			break;
		} else if (d[0] == '\n') {
			break;
		} else if ((d[0] == ':') && attrLen) {
			valueFound = 1;
			while (mpRead(mpp, d, 1) == 1) {
				if (!isspace(d[0])) {
					mpPutBack(mpp, d, 1);
					break;
				} 
			}
		} else if (!valueFound) {
			if (!isspace(*d)) {
				if (attrLen < (attrSpace - 1)) {
					attr[attrLen++] = *d;
				}
			}		
		} else if (valueFound) {	
			if (valueLen < (valueSpace - 1)) {
				value[valueLen++] = *d;
			}
		}
	}
	if (attrSpace) {
		attr[attrLen] = '\0';
	}
	if (valueSpace) {
		value[valueLen] = '\0';
	}
	if (attrLen && valueLen) {
		return 1;
	} else {
		return 0;
	}
}

static cgiParseResultType cgiParseGetFormInput() {
	return cgiParseFormInput(cgiQueryString, cgiContentLength);
}

typedef enum {
	cgiEscapeRest,
	cgiEscapeFirst,
	cgiEscapeSecond
} cgiEscapeState;

typedef enum {
	cgiUnescapeSuccess,
	cgiUnescapeMemory
} cgiUnescapeResultType;

static cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len);

static cgiParseResultType cgiParseFormInput(char *data, int length) {
	/* Scan for pairs, unescaping and storing them as they are found. */
	int pos = 0;
	cgiFormEntry *n;
	cgiFormEntry *l = 0;
	while (pos != length) {
		int foundEq = 0;
		int foundAmp = 0;
		int start = pos;
		int len = 0;
		char *attr;
		char *value;
		while (pos != length) {
			if (data[pos] == '=') {
				foundEq = 1;
				pos++;
				break;
			}
			pos++;
			len++;
		}
		if (!foundEq) {
			break;
		}
		if (cgiUnescapeChars(&attr, data+start, len)
			!= cgiUnescapeSuccess) {
			return cgiParseMemory;
		}	
		start = pos;
		len = 0;
		while (pos != length) {
			if (data[pos] == '&') {
				foundAmp = 1;
				pos++;
				break;
			}
			pos++;
			len++;
		}
		/* The last pair probably won't be followed by a &, but
			that's fine, so check for that after accepting it */
		if (cgiUnescapeChars(&value, data+start, len)
			!= cgiUnescapeSuccess) {
			free(attr);
			return cgiParseMemory;
		}	
		/* OK, we have a new pair, add it to the list. */
		n = (cgiFormEntry *) malloc(sizeof(cgiFormEntry));	
		if (!n) {
			free(attr);
			free(value);
			return cgiParseMemory;
		}
		n->attr = attr;
		n->value = value;
		n->valueLength = strlen(n->value);
		n->fileName = (char *) malloc(1);
		if (!n->fileName) {
			free(attr);
			free(value);
			free(n);
			return cgiParseMemory;
		}	
		n->fileName[0] = '\0';
		n->contentType = (char *) malloc(1);
		if (!n->contentType) {
			free(attr);
			free(value);
			free(n->fileName);
			free(n);
			return cgiParseMemory;
		}	
		n->contentType[0] = '\0';
		n->tfileName = (char *) malloc(1);
		if (!n->tfileName) {
			free(attr);
			free(value);
			free(n->fileName);
			free(n->contentType);
			free(n);
			return cgiParseMemory;
		}	
		n->tfileName[0] = '\0';
		n->next = 0;
		if (!l) {
			cgiFormEntryFirst = n;
		} else {
			l->next = n;
		}
		l = n;
		if (!foundAmp) {
			break;
		}			
	}
	return cgiParseSuccess;
}

static int cgiHexValue[256];

cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len) {
	char *s;
	cgiEscapeState escapeState = cgiEscapeRest;
	int escapedValue = 0;
	int srcPos = 0;
	int dstPos = 0;
	s = (char *) malloc(len + 1);
	if (!s) {
		return cgiUnescapeMemory;
	}
	while (srcPos < len) {
		int ch = cp[srcPos];
		switch (escapeState) {
			case cgiEscapeRest:
			if (ch == '%') {
				escapeState = cgiEscapeFirst;
			} else if (ch == '+') {
				s[dstPos++] = ' ';
			} else {
				s[dstPos++] = ch;	
			}
			break;
			case cgiEscapeFirst:
			escapedValue = cgiHexValue[ch] << 4;	
			escapeState = cgiEscapeSecond;
			break;
			case cgiEscapeSecond:
			escapedValue += cgiHexValue[ch];

⌨️ 快捷键说明

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