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

📄 webs.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 5 页
字号:
	websSetEmfEnvironment(wp);#endif}/******************************************************************************//* *	Define a webs (CGI) variable for this connection. Also create in relevant *	scripting engines. Note: the incoming value may be volatile.  */void websSetVar(webs_t wp, char_t *var, char_t *value){	value_t		 v;	a_assert(websValid(wp));/* *	value_instring will allocate the string if required. */	if (value) {		v = valueString(value, VALUE_ALLOCATE);	} else {		v = valueString(T(""), VALUE_ALLOCATE);	}	symEnter(wp->cgiVars, var, v, 0);}/******************************************************************************//* *	Return TRUE if a webs variable exists for this connection. */int websTestVar(webs_t wp, char_t *var){	sym_t		*sp;	a_assert(websValid(wp));	if (var == NULL || *var == '\0') {		return 0;	}	if ((sp = symLookup(wp->cgiVars, var)) == NULL) {		return 0;	}	return 1;}/******************************************************************************//* *	Get a webs variable but return a default value if string not found. *	Note, defaultGetValue can be NULL to permit testing existence. */char_t *websGetVar(webs_t wp, char_t *var, char_t *defaultGetValue){	sym_t	*sp;	a_assert(websValid(wp));	a_assert(var && *var); 	if ((sp = symLookup(wp->cgiVars, var)) != NULL) {		a_assert(sp->content.type == string);		if (sp->content.value.string) {			return sp->content.value.string;		} else {			return T("");		}	}	return defaultGetValue;}/******************************************************************************//* *	Return TRUE if a webs variable is set to a given value */int websCompareVar(webs_t wp, char_t *var, char_t *value){	a_assert(websValid(wp));	a_assert(var && *var); 	if (gstrcmp(value, websGetVar(wp, var, T(" __UNDEF__ "))) == 0) {		return 1;	}	return 0;}/******************************************************************************//* *	Cancel the request timeout. Note may be called multiple times. */void websTimeoutCancel(webs_t wp){	a_assert(websValid(wp));	if (wp->timeout >= 0) {		emfUnschedCallback(wp->timeout);		wp->timeout = -1;	}}/******************************************************************************//* *	Output a HTTP response back to the browser. If redirect is set to a  *	URL, the browser will be sent to this location. */void websResponse(webs_t wp, int code, char_t *message, char_t *redirect){	char_t		*date;	a_assert(websValid(wp));/* *	IE3.0 needs no Keep Alive for some return codes. */	wp->flags &= ~WEBS_KEEP_ALIVE;/* *	Only output the header if a header has not already been output. */	if ( !(wp->flags & WEBS_HEADER_DONE)) {		wp->flags |= WEBS_HEADER_DONE;		websWrite(wp, T("HTTP/1.1 %d %s\r\n"), code, websErrorMsg(code));/*		 *		By license terms the following line of code must not be modified. */		websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);/*		 *		Timestamp/Date is usually the next to go */		if ((date = websGetDateString(NULL)) != NULL) {			websWrite(wp, T("Date: %s\r\n"), date);			bfree(B_L, date);		}/* *		If authentication is required, send the auth header info */		if (code == 401) {			if (!(wp->flags & WEBS_AUTH_DIGEST)) {				websWrite(wp, T("WWW-Authenticate: Basic realm=\"%s\"\r\n"), 					websGetRealm());#ifdef DIGEST_ACCESS_SUPPORT			} else {				char_t *nonce, *opaque;				nonce = websCalcNonce(wp), 				opaque = websCalcOpaque(wp), 				websWrite(wp, 					T("WWW-Authenticate: Digest realm=\"%s\", domain=\"%s\",")					T("qop=\"%s\", nonce=\"%s\", opaque=\"%s\",")					T("algorithm=\"%s\", stale=\"%s\"\r\n"), 					websGetRealm(),					websGetHostUrl(),					T("auth"),					nonce,					opaque, T("MD5"), T("FALSE"));				bfree(B_L, nonce);				bfree(B_L, opaque);#endif			}		}		if (wp->flags & WEBS_KEEP_ALIVE) {			websWrite(wp, T("Connection: keep-alive\r\n"));		}		websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));		websWrite(wp, T("Content-Type: text/html\r\n"));/* *		We don't do a string length here as the message may be multi-line.  *		Ie. <CR><LF> will count as only one and we will have a content-length  *		that is too short. * *		websWrite(wp, T("Content-Length: %s\r\n"), message); */		if (redirect) {			websWrite(wp, T("Location: %s\r\n"), redirect);		}		websWrite(wp, T("\r\n"));	}/* *	If the browser didn't do a HEAD only request, send the message as well. */	if ((wp->flags & WEBS_HEAD_REQUEST) == 0 && message && *message) {		websWrite(wp, T("%s\r\n"), message);	}	websDone(wp, code);}/******************************************************************************//* *	Redirect the user to another webs page */void websRedirect(webs_t wp, char_t *url){	char_t	*msgbuf, *urlbuf, *redirectFmt;	a_assert(websValid(wp));	a_assert(url);	websStats.redirects++;	msgbuf = urlbuf = NULL;/* *	Some browsers require a http://host qualified URL for redirection */	if (gstrstr(url, T("http://")) == NULL) {		if (*url == '/') {			url++;		}		redirectFmt = T("http://%s/%s");#ifdef WEBS_SSL_SUPPORT		if (wp->flags & WEBS_SECURE) {			redirectFmt = T("https://%s/%s");		}#endif		fmtAlloc(&urlbuf, WEBS_MAX_URL + 80, redirectFmt,			websGetVar(wp, T("HTTP_HOST"), 	websHostUrl), url);		url = urlbuf;	}/* *	Add human readable message for completeness. Should not be required. */	fmtAlloc(&msgbuf, WEBS_MAX_URL + 80, 		T("<html><head></head><body>\r\n\		This document has moved to a new <a href=\"%s\">location</a>.\r\n\		Please update your documents to reflect the new location.\r\n\		</body></html>\r\n"), url);	websResponse(wp, 302, msgbuf, url);	bfreeSafe(B_L, msgbuf);	bfreeSafe(B_L, urlbuf);}/******************************************************************************//*	 *	Output an error message and cleanup */void websError(webs_t wp, int code, char_t *fmt, ...){	va_list		args;	char_t		*msg, *userMsg, *buf;	a_assert(websValid(wp));	a_assert(fmt);	websStats.errors++;	va_start(args, fmt);	userMsg = NULL;	fmtValloc(&userMsg, WEBS_BUFSIZE, fmt, args);	va_end(args);	msg = T("<html><head><title>Document Error: %s</title></head>\r\n\		<body><h2>Access Error: %s</h2>\r\n\		when trying to obtain <b>%s</b><br><p>%s</p></body></html>\r\n");/* *	Ensure we have plenty of room */	buf = NULL;	fmtAlloc(&buf, WEBS_BUFSIZE, msg, websErrorMsg(code), 		websErrorMsg(code), wp->url, userMsg);	websResponse(wp, code, buf, NULL);	bfreeSafe(B_L, buf);	bfreeSafe(B_L, userMsg);}/******************************************************************************//* *	Return the error message for a given code */static char_t *websErrorMsg(int code){	websErrorType	*ep;	for (ep = websErrors; ep->code; ep++) {		if (code == ep->code) {			return ep->msg;		}	}	a_assert(0);	return T("");}/******************************************************************************//* *	Do formatted output to the browser. This is the public ASP and form *	write procedure. */int websWrite(webs_t wp, char_t *fmt, ...){	va_list		 vargs;	char_t		*buf;	int			 rc;		a_assert(websValid(wp));	va_start(vargs, fmt);	buf = NULL;	rc = 0;	if (fmtValloc(&buf, WEBS_BUFSIZE, fmt, vargs) >= WEBS_BUFSIZE) {		trace(0, T("webs: websWrite lost data, buffer overflow\n"));	}	va_end(vargs);	a_assert(buf);	if (buf) {		rc = websWriteBlock(wp, buf, gstrlen(buf));		bfree(B_L, buf);	}	return rc;}/******************************************************************************//* *	Write a block of data of length "nChars" to the user's browser. Public *	write block procedure.  If unicode is turned on this function expects  *	buf to be a unicode string and it converts it to ASCII before writing. *	See websWriteDataNonBlock to always write binary or ASCII data with no  *	unicode conversion.  This returns the number of char_t's processed. *	It spins until nChars are flushed to the socket.  For non-blocking *	behavior, use websWriteDataNonBlock. */int websWriteBlock(webs_t wp, char_t *buf, int nChars){	int		len, done;	char	*asciiBuf, *pBuf;	a_assert(wp);	a_assert(websValid(wp));	a_assert(buf);	a_assert(nChars >= 0);	done = len = 0;/* *	ballocUniToAsc will convert Unicode to strings to Ascii.  If Unicode is *	not turned on then ballocUniToAsc will not do the conversion. */	pBuf = asciiBuf = ballocUniToAsc(buf, nChars);	while (nChars > 0) {  #ifdef WEBS_SSL_SUPPORT		if (wp->flags & WEBS_SECURE) {			if ((len = websSSLWrite(wp->wsp, pBuf, nChars)) < 0) {				bfree(B_L, asciiBuf);				return -1;			}			websSSLFlush(wp->wsp);		} else {			if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {				bfree(B_L, asciiBuf);				return -1;			}			socketFlush(wp->sid);		}#else /* ! WEBS_SSL_SUPPORT */		if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {			bfree(B_L, asciiBuf);			return -1;		}		socketFlush(wp->sid);#endif /* WEBS_SSL_SUPPORT */		nChars -= len;		pBuf += len;		done += len;	}	bfree(B_L, asciiBuf);	return done;}/******************************************************************************//* *	Write a block of data of length "nChars" to the user's browser. Same as *	websWriteBlock except that it expects straight ASCII or binary and does no *	unicode conversion before writing the data.  If the socket cannot hold all *	the data, it will return the number of bytes flushed to the socket before *	it would have blocked.  This returns the number of chars processed or -1 *	if socketWrite fails. */int websWriteDataNonBlock(webs_t wp, char *buf, int nChars){	int r;	a_assert(wp);	a_assert(websValid(wp));	a_assert(buf);	a_assert(nChars >= 0);#ifdef WEBS_SSL_SUPPORT	if (wp->flags & WEBS_SECURE) {		r = websSSLWrite(wp->wsp, buf, nChars);		websSSLFlush(wp->wsp);	} else {		r = socketWrite(wp->sid, buf, nChars);		socketFlush(wp->sid);	}#else	r = socketWrite(wp->sid, buf, nChars);	socketFlush(wp->sid);#endif	return r;}/******************************************************************************//* *	Decode a URL (or part thereof). Allows insitu decoding. */void websDecodeUrl(char_t *decoded, char_t *token, int len){	char_t	*ip,  *op;	int		num, i, c;		a_assert(decoded);	a_assert(token);	op = decoded;	for (ip = token; *ip && len > 0; ip++, op++) {		if (*ip == '+') {			*op = ' ';		} else if (*ip == '%' && gisxdigit(ip[1]) && gisxdigit(ip[2])) {/* *			Convert %nn to a single character */			ip++;			for (i = 0, num = 0; i < 2; i++, ip++) {				c = tolower(*ip);				if (c >= 'a' && c <= 'f') {					num = (num * 16) + 10 + c - 'a';				} else {					num = (num * 16) + c - '0';				}			}			*op = (char_t) num;			ip--;		} else {			*op = *ip;		}		len--;	}	*op = '\0';}/******************************************************************************/#if WEBS_LOG_SUPPORT/* *	Output a log message */static void websLog(webs_t wp, int code){	char_t	*buf;	char	*abuf;	int		len;	a_assert(websValid(wp));	buf = NULL;	fmtAlloc(&buf, WEBS_MAX_URL + 80, T("%d %s %d %d\n"), time(0), 		wp->url, code, wp->written);	len = gstrlen(buf);	abuf = ballocUniToAsc(buf, len+1);	write(websLogFd, abuf, len);	bfreeSafe(B_L, buf);	bfreeSafe(B_L, abuf);}#endif /* WEBS_LOG_SUPPORT *//******************************************************************************//* *	Request timeout. The timeout triggers if we have not read any data from *	the users browser in the last WEBS_TIMEOUT period. If we have heard from *	the browser, simply re-issue the timeout. */void websTimeout(void *arg, int id){	webs_t		wp;	int			delay, tm;	wp = (webs_t) arg;	a_assert(websValid(wp));	tm = websGetTimeSinceMark(wp) * 1000;	if (tm >= WEBS_TIMEOUT) {		websStats.timeouts++;		emfUnschedCallback(id);/* *		Clear the timeout id */		wp->timeout = -1;		websDone(wp, 404);	} else {		delay = WEBS_TIMEOUT - tm;		a_assert(delay > 0);		emfReschedCallback(id, delay);	}}/******************************************************************************//* *	Called when the request is done. */void websDone(webs_t wp, int code){	a_assert(websValid(wp));/* * 	Disable socket handler in case keep alive set. */	socketDeleteHandler(wp->sid);	if (code != 200) {		wp->flags &= ~WEBS_KEEP_ALIVE;	}#if WEBS_PROXY_SUPPORT	if (! (wp->flags & WEBS_LOCAL_PAGE)) {		websStats.activeNetRequests--;	}#endif#if WEBS_LOG_SUPPORT	if (! (wp->flags & WEBS_REQUEST_DONE)) {		websLog(wp, code);	}#endif/* *	Close any opened document by a handler */	websPageClose(wp);/* *	Exit if secure. */#ifdef WEBS_SSL_SUPPORT	if (wp->flags & WEBS_SECURE) {		websTimeoutCancel(wp);		websSSLFlush(wp->wsp);		socketCloseConnection(wp->sid);		websFree(wp);		return;

⌨️ 快捷键说明

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