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

📄 webs.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 5 页
字号:
                    		websDone(wp, 0);                  	}	                /* End of bugfix */			return -1;		} else {								/* Valid data *//* *			Convert to UNICODE if necessary.  First be sure the string  *			is NULL terminated. */			buf[nbytes] = '\0';			if ((text = ballocAscToUni(buf, nbytes)) == NULL) {				websError(wp, 503, T("Insufficient memory"));				return -1;			}		}	} else {#ifdef WEBS_SSL_SUPPORT		if (wp->flags & WEBS_SECURE) {			nbytes = websSSLGets(wp->wsp, &text);		} else {			nbytes = socketGets(wp->sid, &text);		}#else		nbytes = socketGets(wp->sid, &text);#endif		if (nbytes < 0) {			int eof;/* *			Error, EOF or incomplete */#ifdef WEBS_SSL_SUPPORT			if (wp->flags & WEBS_SECURE) {/* *				If state is WEBS_BEGIN and the request is secure, a -1 will  *				usually	indicate SSL negotiation */				if (wp->state == WEBS_BEGIN) {					eof = 1;				} else {					eof = websSSLEof(wp->wsp);				}			} else {				eof = socketEof(wp->sid);			}#else			eof = socketEof(wp->sid);#endif			if (eof) {/* *				If this is a post request without content length, process  *				the request as we now have all the data. Otherwise just  *				close the connection. */				if (wp->state == WEBS_POST) {					websUrlHandlerRequest(wp);				} else {					websDone(wp, 0);				}			}/* *			If state is WEBS_HEADER and the ringq is empty, then this is a *			simple request with no additional header fields to process and *			no empty line terminator. */			if (wp->state == WEBS_HEADER && ringqLen(&wp->header) <= 0) {				websParseRequest(wp);				websUrlHandlerRequest(wp);			}			return -1;		} else if (nbytes == 0) {			if (wp->state == WEBS_HEADER) {/* *				Valid empty line, now finished with header */				websParseRequest(wp);				if (wp->flags & WEBS_POST_REQUEST) {					if (wp->flags & WEBS_CLEN) {						wp->state = WEBS_POST_CLEN;						clen = wp->clen;					} else {						wp->state = WEBS_POST;						clen = 1;					}					if (clen > 0) {/* *						Return 0 to get more data. */						return 0;					}					return 1;				}/* *				We've read the header so go and handle the request */				websUrlHandlerRequest(wp);			}			return -1;		}	}	a_assert(text);	a_assert(nbytes > 0);	*ptext = text;	*pnbytes = nbytes;	return 1;}/******************************************************************************//* *	Parse the first line of a HTTP request */static int websParseFirst(webs_t wp, char_t *text){	char_t 	*op, *proto, *protoVer, *url, *host, *query, *path, *port, *ext;	char_t	*buf;	int		testPort;	a_assert(websValid(wp));	a_assert(text && *text);/* *	Determine the request type: GET, HEAD or POST */	op = gstrtok(text, T(" \t"));	if (op == NULL || *op == '\0') {		websError(wp, 400, T("Bad HTTP request"));		return -1;	}	if (gstrcmp(op, T("GET")) != 0) {		if (gstrcmp(op, T("POST")) == 0) {			wp->flags |= WEBS_POST_REQUEST;		} else if (gstrcmp(op, T("HEAD")) == 0) {			wp->flags |= WEBS_HEAD_REQUEST;		} else {			websError(wp, 400, T("Bad request type"));			return -1;		}	}/* *	Store result in the form (CGI) variable store */	websSetVar(wp, T("REQUEST_METHOD"), op);	url = gstrtok(NULL, T(" \t\n"));	if (url == NULL || *url == '\0') {		websError(wp, 400, T("Bad HTTP request"));		return -1;	}	protoVer = gstrtok(NULL, T(" \t\n"));/* *	Parse the URL and store all the various URL components. websUrlParse *	returns an allocated buffer in buf which we must free. We support both *	proxied and non-proxied requests. Proxied requests will have http://host/ *	at the start of the URL. Non-proxied will just be local path names. */	host = path = port = proto = query = ext = NULL;	if (websUrlParse(url, &buf, &host, &path, &port, &query, &proto, 			NULL, &ext) < 0) {		websError(wp, 400, T("Bad URL format"));		return -1;	}	wp->url = bstrdup(B_L, url);#ifndef __NO_CGI_BIN	if (gstrstr(url, CGI_BIN) != NULL) {		wp->flags |= WEBS_CGI_REQUEST;		if (wp->flags & WEBS_POST_REQUEST) {			wp->cgiStdin = websGetCgiCommName();		}	}#endif	wp->query = bstrdup(B_L, query);	wp->host = bstrdup(B_L, host);	wp->path = bstrdup(B_L, path);	wp->protocol = bstrdup(B_L, proto);	wp->protoVersion = bstrdup(B_L, protoVer);		if ((testPort = socketGetPort(wp->listenSid)) >= 0) {		wp->port = testPort;	} else {		wp->port = gatoi(port);	}	if (gstrcmp(ext, T(".asp")) == 0) {		wp->flags |= WEBS_ASP;	}	bfree(B_L, buf);	websUrlType(url, wp->type, TSZ(wp->type));#if WEBS_PROXY_SUPPORT/* *	Determine if this is a request for local webs data. If it is not a proxied  *	request from the browser, we won't see the "http://" or the system name, so *	we assume it must be talking to us directly for local webs data. *	Note: not fully implemented yet. */	if (gstrstr(wp->url, T("http://")) == NULL || 		((gstrcmp(wp->host, T("localhost")) == 0 || 			gstrcmp(wp->host, websHost) == 0) && (wp->port == websPort))) {		wp->flags |= WEBS_LOCAL_PAGE;		if (gstrcmp(wp->path, T("/")) == 0) {			wp->flags |= WEBS_HOME_PAGE;		}	}#endif	ringqFlush(&wp->header);	return 0;}/******************************************************************************//* *	Parse a full request */#define isgoodchar(s) (gisalnum((s)) || ((s) == '/') || ((s) == '_') || \						((s) == '.')  || ((s) == '-') )static void websParseRequest(webs_t wp){	char_t	*authType, *upperKey, *cp, *browser, *lp, *key, *value;	a_assert(websValid(wp));/* *	Define default CGI values */	websSetVar(wp, T("HTTP_AUTHORIZATION"), T(""));/*  *	Parse the header and create the Http header keyword variables *	We rewrite the header as we go for non-local requests.  NOTE: this * 	modifies the header string directly and tokenizes each line with '\0'. */	browser = NULL;	for (lp = (char_t*) wp->header.servp; lp && *lp; ) {		cp = lp;		if ((lp = gstrchr(lp, '\n')) != NULL) {			lp++;		}		if ((key = gstrtok(cp, T(": \t\n"))) == NULL) {			continue;		}		if ((value = gstrtok(NULL, T("\n"))) == NULL) {			value = T("");		}		while (gisspace(*value)) {			value++;		}		strlower(key);/* *		Create a variable (CGI) for each line in the header */		fmtAlloc(&upperKey, (gstrlen(key) + 6), T("HTTP_%s"), key);		for (cp = upperKey; *cp; cp++) {			if (*cp == '-')				*cp = '_';		}		strupper(upperKey);		websSetVar(wp, upperKey, value);		bfree(B_L, upperKey);/* *		Track the requesting agent (browser) type */		if (gstrcmp(key, T("user-agent")) == 0) {			wp->userAgent = bstrdup(B_L, value);/* *		Parse the user authorization. ie. password */		} else if (gstricmp(key, T("authorization")) == 0) {/* *			Determine the type of Authorization Request */			authType = bstrdup (B_L, value);			a_assert (authType);/*			 *			Truncate authType at the next non-alpha character */			cp = authType;			while (gisalpha(*cp)) {				cp++;			}			*cp = '\0';			wp->authType = bstrdup(B_L, authType);			bfree(B_L, authType);			if (gstricmp(wp->authType, T("basic")) == 0) {				char_t	userAuth[FNAMESIZE];/* *				The incoming value is username:password (Basic authentication) */				if ((cp = gstrchr(value, ' ')) != NULL) {					*cp = '\0';					wp->authType = bstrdup(B_L, value);					websDecode64(userAuth, ++cp, sizeof(userAuth));				} else {					websDecode64(userAuth, value, sizeof(userAuth));				}/* *				Split userAuth into userid and password */				if ((cp = gstrchr(userAuth, ':')) != NULL) {					*cp++ = '\0';				}				if (cp) {					wp->userName = bstrdup(B_L, userAuth);					wp->password = bstrdup(B_L, cp);				} else {					wp->userName = bstrdup(B_L, T(""));					wp->password = bstrdup(B_L, T(""));				}/* *				Set the flags to indicate digest authentication */				wp->flags |= WEBS_AUTH_BASIC;			} else {#ifdef DIGEST_ACCESS_SUPPORT/* *				The incoming value is slightly more complicated (Digest) */				char_t *np;		/* pointer to end of tag name */				char_t tp;		/* temporary character holding space */				char_t *vp;		/* pointer to value */				char_t *npv;	/* pointer to end of value, "next" pointer */				char_t tpv;		/* temporary character holding space *//* *				Set the flags to indicate digest authentication */				wp->flags |= WEBS_AUTH_DIGEST;/* *				Move cp to Next word beyond "Digest", *				vp to first char after '='. */ 				cp = value;				while (isgoodchar(*cp)) {					cp++;				}				while (!isgoodchar(*cp)) {					cp++;				}/* *				Find beginning of value */				vp = gstrchr(cp, '=');				while (vp) {/* *					Zero-terminate tag name */					np = cp;					while (isgoodchar(*np)) {						np++;					}					tp = *np;					*np = 0;/* *					Advance value pointer to first legit character */					vp++;					while (!isgoodchar(*vp)) {						vp++;					}/* *					Zero-terminate value */					npv = vp;					while (isgoodchar(*npv)) {						npv++;					}					tpv = *npv;					*npv = 0;/* *					Extract the fields */					if (gstricmp(cp, T("username")) == 0) {						wp->userName = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("response")) == 0) {						wp->digest = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("opaque")) == 0) {						wp->opaque = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("uri")) == 0) {						wp->uri = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("realm")) == 0) {						wp->realm = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("nonce")) == 0) {						wp->nonce = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("nc")) == 0) {						wp->nc = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("cnonce")) == 0) {						wp->cnonce = bstrdup(B_L, vp);					} else if (gstricmp(cp, T("qop")) == 0) {						wp->qop = bstrdup(B_L, vp);					}/* *					Restore tag name and value zero-terminations */					*np = tp;					*npv = tpv;/* *					Advance tag name and value pointers */ 					cp = npv;					while (*cp && isgoodchar(*cp)) {						cp++;					}					while (*cp && !isgoodchar(*cp)) {						cp++;					}					if (*cp) {						vp = gstrchr(cp, '=');					} else {						vp = NULL;					}				}#endif /* DIGEST_ACCESS_SUPPORT */			} /* if (gstrcmp(wp->authType)) *//* *		Parse the content length */		} else if (gstrcmp(key, T("content-length")) == 0) {			wp->flags |= WEBS_CLEN;			wp->clen = gatoi(value);			websSetVar(wp, T("CONTENT_LENGTH"), value);/* *		Parse the content type */		} else if (gstrcmp(key, T("content-type")) == 0) {			websSetVar(wp, T("CONTENT_TYPE"), value);#if WEBS_KEEP_ALIVE_SUPPORT		} else if (gstrcmp(key, T("connection")) == 0) {			strlower(value);			if (gstrcmp(value, T("keep-alive")) == 0) {				wp->flags |= WEBS_KEEP_ALIVE;			}#endif#if WEBS_PROXY_SUPPORT/* *		This may be useful if you wish to keep a local cache of web pages *		for proxied requests. */		} else if (gstrcmp(key, T("pragma")) == 0) {			char_t	tmp[256];			gstrncpy(tmp, value, TSZ(tmp));			strlower(tmp);			if (gstrstr(tmp, T("no-cache"))) {				wp->flags |= WEBS_DONT_USE_CACHE;			}#endif /* WEBS_PROXY_SUPPORT *//* *		Store the cookie */		} else if (gstrcmp(key, T("cookie")) == 0) {			wp->flags |= WEBS_COOKIE;			wp->cookie = bstrdup(B_L, value);#if WEBS_IF_MODIFIED_SUPPORT/* *		See if the local page has been modified since the browser last *		requested this document. If not, just return a 302 */		} else if (gstrcmp(key, T("if-modified-since")) == 0) {			char_t *cmd;			time_t tip = 0;			if ((cp = gstrchr(value, ';')) != NULL) {				*cp = '\0';			}			fmtAlloc(&cmd, 64, T("%s"), value);			if ((wp->since = dateParse(tip, cmd)) != 0) {				wp->flags |= WEBS_IF_MODIFIED;			}			bfreeSafe(B_L, cmd);#endif /* WEBS_IF_MODIFIED_SUPPORT */		}	}}/******************************************************************************//* *	Set the variable (CGI) environment for this request. Create variables *	for all standard CGI variables. Also decode the query string and create *	a variable for each name=value pair. */void websSetEnv(webs_t wp){	char_t	portBuf[8];	char_t	*keyword, *value, *valCheck, *valNew;	a_assert(websValid(wp));	websSetVar(wp, T("QUERY_STRING"), wp->query);	websSetVar(wp, T("GATEWAY_INTERFACE"), T("CGI/1.1"));	websSetVar(wp, T("SERVER_HOST"), websHost);	websSetVar(wp, T("SERVER_NAME"), websHost);	websSetVar(wp, T("SERVER_URL"), websHostUrl);	websSetVar(wp, T("REMOTE_HOST"), wp->ipaddr);	websSetVar(wp, T("REMOTE_ADDR"), wp->ipaddr);	websSetVar(wp, T("PATH_INFO"), wp->path);	stritoa(websPort, portBuf, sizeof(portBuf));	websSetVar(wp, T("SERVER_PORT"), portBuf);	websSetVar(wp, T("SERVER_ADDR"), websIpaddr);	fmtAlloc(&value, FNAMESIZE, T("%s/%s"), WEBS_NAME, WEBS_VERSION);	websSetVar(wp, T("SERVER_SOFTWARE"), value);	bfreeSafe(B_L, value);	websSetVar(wp, T("SERVER_PROTOCOL"), wp->protoVersion);/* *	Decode and create an environment query variable for each query keyword. *	We split into pairs at each '&', then split pairs at the '='. *	Note: we rely on wp->decodedQuery preserving the decoded values in the *	symbol table. */	wp->decodedQuery = bstrdup(B_L, wp->query);	keyword = gstrtok(wp->decodedQuery, T("&"));	while (keyword != NULL) {		if ((value = gstrchr(keyword, '=')) != NULL) {			*value++ = '\0';			websDecodeUrl(keyword, keyword, gstrlen(keyword));			websDecodeUrl(value, value, gstrlen(value));		} else {			value = T("");		}		if (*keyword) {/* *			If keyword has already been set, append the new value to what has  *			been stored. */			if ((valCheck = websGetVar(wp, keyword, NULL)) != 0) {				fmtAlloc(&valNew, 256, T("%s %s"), valCheck, value);				websSetVar(wp, keyword, valNew);				bfreeSafe(B_L, valNew);			} else {				websSetVar(wp, keyword, value);			}		}		keyword = gstrtok(NULL, T("&"));	}#if EMF/* *	Add GoAhead Embedded Management Framework defines */

⌨️ 快捷键说明

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