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

📄 parse.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <libsec.h>#include <bin.h>#include <httpd.h>#include "escape.h"typedef struct Hlex	Hlex;typedef struct MimeHead	MimeHead;enum{	/*	 * tokens	 */	Word	= 1,	QString,};#define UlongMax	4294967295ULstruct Hlex{	int	tok;	int	eoh;	int	eol;			/* end of header line encountered? */	uchar	*hstart;		/* start of header */	jmp_buf	jmp;			/* jmp here to parse header */	char	wordval[HMaxWord];	HConnect *c;};struct MimeHead{	char	*name;	void	(*parse)(Hlex*, char*);	uchar	seen;	uchar	ignore;};static void	mimeaccept(Hlex*, char*);static void	mimeacceptchar(Hlex*, char*);static void	mimeacceptenc(Hlex*, char*);static void	mimeacceptlang(Hlex*, char*);static void	mimeagent(Hlex*, char*);static void	mimeauthorization(Hlex*, char*);static void	mimeconnection(Hlex*, char*);static void	mimecontlen(Hlex*, char*);static void	mimeexpect(Hlex*, char*);static void	mimefresh(Hlex*, char*);static void	mimefrom(Hlex*, char*);static void	mimehost(Hlex*, char*);static void	mimeifrange(Hlex*, char*);static void	mimeignore(Hlex*, char*);static void	mimematch(Hlex*, char*);static void	mimemodified(Hlex*, char*);static void	mimenomatch(Hlex*, char*);static void	mimerange(Hlex*, char*);static void	mimetransenc(Hlex*, char*);static void	mimeunmodified(Hlex*, char*);/* * headers seen also include * allow  cache-control chargeto * content-encoding content-language content-location content-md5 content-range content-type * date etag expires forwarded last-modified max-forwards pragma * proxy-agent proxy-authorization proxy-connection * ua-color ua-cpu ua-os ua-pixels * upgrade via x-afs-tokens x-serial-number */static MimeHead	mimehead[] ={	{"accept",		mimeaccept},	{"accept-charset",	mimeacceptchar},	{"accept-encoding",	mimeacceptenc},	{"accept-language",	mimeacceptlang},	{"authorization",	mimeauthorization},	{"connection",		mimeconnection},	{"content-length",	mimecontlen},	{"expect",		mimeexpect},	{"fresh",		mimefresh},	{"from",		mimefrom},	{"host",		mimehost},	{"if-match",		mimematch},	{"if-modified-since",	mimemodified},	{"if-none-match",	mimenomatch},	{"if-range",		mimeifrange},	{"if-unmodified-since",	mimeunmodified},	{"range",		mimerange},	{"transfer-encoding",	mimetransenc},	{"user-agent",		mimeagent},};char*		hmydomain;char*		hversion = "HTTP/1.1";static	void	lexhead(Hlex*);static	void	parsejump(Hlex*, char*);static	int	getc(Hlex*);static	void	ungetc(Hlex*);static	int	wordcr(Hlex*);static	int	wordnl(Hlex*);static	void	word(Hlex*, char*);static	int	lex1(Hlex*, int);static	int	lex(Hlex*);static	int	lexbase64(Hlex*);static	ulong	digtoul(char *s, char **e);/* * flush an clean up junk from a request */voidhreqcleanup(HConnect *c){	int i;	hxferenc(&c->hout, 0);	memset(&c->req, 0, sizeof(c->req));	memset(&c->head, 0, sizeof(c->head));	c->hpos = c->header;	c->hstop = c->header;	binfree(&c->bin);	for(i = 0; i < nelem(mimehead); i++){		mimehead[i].seen = 0;		mimehead[i].ignore = 0;	}}/* * list of tokens * if the client is HTTP/1.0, * ignore headers which match one of the tokens. * restarts parsing if necessary. */static voidmimeconnection(Hlex *h, char *){	char *u, *p;	int reparse, i;	reparse = 0;	for(;;){		while(lex(h) != Word)			if(h->tok != ',')				goto breakout;		if(cistrcmp(h->wordval, "keep-alive") == 0)			h->c->head.persist = 1;		else if(cistrcmp(h->wordval, "close") == 0)			h->c->head.closeit = 1;		else if(!http11(h->c)){			for(i = 0; i < nelem(mimehead); i++){				if(cistrcmp(mimehead[i].name, h->wordval) == 0){					reparse = mimehead[i].seen && !mimehead[i].ignore;					mimehead[i].ignore = 1;					if(cistrcmp(mimehead[i].name, "authorization") == 0){						h->c->head.authuser = nil;						h->c->head.authpass = nil;					}				}			}		}		if(lex(h) != ',')			break;	}breakout:;	/*	 * if need to ignore headers we've already parsed,	 * reset & start over.  need to save authorization	 * info because it's written over when parsed.	 */	if(reparse){		u = h->c->head.authuser;		p = h->c->head.authpass;		memset(&h->c->head, 0, sizeof(h->c->head));		h->c->head.authuser = u;		h->c->head.authpass = p;		h->c->hpos = h->hstart;		longjmp(h->jmp, 1);	}}inthparseheaders(HConnect *c, int timeout){	Hlex h;	c->head.fresh_thresh = 0;	c->head.fresh_have = 0;	c->head.persist = 0;	if(c->req.vermaj == 0){		c->head.host = hmydomain;		return 1;	}	memset(&h, 0, sizeof(h));	h.c = c;	if(timeout)		alarm(timeout);	if(hgethead(c, 1) < 0)		return -1;	if(timeout)		alarm(0);	h.hstart = c->hpos;	if(setjmp(h.jmp) == -1)		return -1;	h.eol = 0;	h.eoh = 0;	h.tok = '\n';	while(lex(&h) != '\n'){		if(h.tok == Word && lex(&h) == ':')			parsejump(&h, hstrdup(c, h.wordval));		while(h.tok != '\n')			lex(&h);		h.eol = h.eoh;	}	if(http11(c)){		/*		 * according to the http/1.1 spec,		 * these rules must be followed		 */		if(c->head.host == nil){			hfail(c, HBadReq, nil);			return -1;		}		if(c->req.urihost != nil)			c->head.host = c->req.urihost;		/*		 * also need to check host is actually this one		 */	}else if(c->head.host == nil)		c->head.host = hmydomain;	return 1;}/* * mimeparams	: | mimeparams ";" mimepara * mimeparam	: token "=" token | token "=" qstring */static HSPairs*mimeparams(Hlex *h){	HSPairs *p;	char *s;	p = nil;	for(;;){		if(lex(h) != Word)			break;		s = hstrdup(h->c, h->wordval);		if(lex(h) != Word && h->tok != QString)			break;		p = hmkspairs(h->c, s, hstrdup(h->c, h->wordval), p);	}	return hrevspairs(p);}/* * mimehfields	: mimehfield | mimehfields commas mimehfield * mimehfield	: token mimeparams * commas	: "," | commas "," */static HFields*mimehfields(Hlex *h){	HFields *f;	f = nil;	for(;;){		while(lex(h) != Word)			if(h->tok != ',')				goto breakout;		f = hmkhfields(h->c, hstrdup(h->c, h->wordval), nil, f);		if(lex(h) == ';')			f->params = mimeparams(h);		if(h->tok != ',')			break;	}breakout:;	return hrevhfields(f);}/* * parse a list of acceptable types, encodings, languages, etc. */static HContent*mimeok(Hlex *h, char *name, int multipart, HContent *head){	char *generic, *specific, *s;	float v;	/*	 * each type is separated by one or more commas	 */	while(lex(h) != Word)		if(h->tok != ',')			return head;	generic = hstrdup(h->c, h->wordval);	lex(h);	if(h->tok == '/' || multipart){		/*		 * at one time, IE5 improperly said '*' for single types		 */		if(h->tok != '/')			return nil;		if(lex(h) != Word)			return head;		specific = hstrdup(h->c, h->wordval);		if(!multipart && strcmp(specific, "*") != 0)			return head;		lex(h);	}else		specific = nil;	head = hmkcontent(h->c, generic, specific, head);	for(;;){		switch(h->tok){		case ';':			/*			 * should make a list of these params			 * for accept, they fall into two classes:			 *	up to a q=..., they modify the media type.			 *	afterwards, they acceptance criteria			 */			if(lex(h) == Word){				s = hstrdup(h->c, h->wordval);				if(lex(h) != '=' || lex(h) != Word && h->tok != QString)					return head;				v = strtod(h->wordval, nil);				if(strcmp(s, "q") == 0)					head->q = v;				else if(strcmp(s, "mxb") == 0)					head->mxb = v;				else{					/* cope with accept: application/xhtml+xml; profile=http://www.wapforum.org/xhtml, */					while(lex(h) == Word || (h->tok != ',' && h->eol == 0) )						;					return mimeok(h, name, multipart, head);				}			}			break;		case ',':			return  mimeok(h, name, multipart, head);		default:			return head;		}		lex(h);	}}/* * parse a list of entity tags * 1#entity-tag * entity-tag = [weak] opaque-tag * weak = "W/" * opaque-tag = quoted-string */static HETag*mimeetag(Hlex *h, HETag *head){	HETag *e;	int weak;	for(;;){		while(lex(h) != Word && h->tok != QString)			if(h->tok != ',')				return head;		weak = 0;		if(h->tok == Word && strcmp(h->wordval, "*") != 0){			if(strcmp(h->wordval, "W") != 0)				return head;			if(lex(h) != '/' || lex(h) != QString)				return head;			weak = 1;		}		e = halloc(h->c, sizeof(HETag));		e->etag = hstrdup(h->c, h->wordval);		e->weak = weak;		e->next = head;		head = e;		if(lex(h) != ',')			return head;	}}/* * ranges-specifier = byte-ranges-specifier * byte-ranges-specifier = "bytes" "=" byte-range-set * byte-range-set = 1#(byte-range-spec|suffix-byte-range-spec) * byte-range-spec = byte-pos "-" [byte-pos] * byte-pos = 1*DIGIT * suffix-byte-range-spec = "-" suffix-length * suffix-length = 1*DIGIT * * syntactically invalid range specifiers cause the * entire header field to be ignored. * it is syntactically incorrect for the second byte pos * to be smaller than the first byte pos */static HRange*mimeranges(Hlex *h, HRange *head){	HRange *r, *rh, *tail;	char *w;	ulong start, stop;	int suf;	if(lex(h) != Word || strcmp(h->wordval, "bytes") != 0 || lex(h) != '=')		return head;	rh = nil;	tail = nil;	for(;;){		while(lex(h) != Word){			if(h->tok != ','){				if(h->tok == '\n')					goto breakout;				return head;			}		}		w = h->wordval;		start = 0;		suf = 1;		if(w[0] != '-'){			suf = 0;			start = digtoul(w, &w);			if(w[0] != '-')				return head;		}		w++;		stop = ~0UL;		if(w[0] != '\0'){			stop = digtoul(w, &w);			if(w[0] != '\0')				return head;			if(!suf && stop < start)				return head;		}		r = halloc(h->c, sizeof(HRange));		r->suffix = suf;		r->start = start;		r->stop = stop;		r->next = nil;		if(rh == nil)			rh = r;		else			tail->next = r;		tail = r;		if(lex(h) != ','){			if(h->tok == '\n')				break;			return head;		}	}breakout:;	if(head == nil)		return rh;	for(tail = head; tail->next != nil; tail = tail->next)		;	tail->next = rh;	return head;}static voidmimeaccept(Hlex *h, char *name){	h->c->head.oktype = mimeok(h, name, 1, h->c->head.oktype);}static voidmimeacceptchar(Hlex *h, char *name){	h->c->head.okchar = mimeok(h, name, 0, h->c->head.okchar);}static voidmimeacceptenc(Hlex *h, char *name){	h->c->head.okencode = mimeok(h, name, 0, h->c->head.okencode);}static voidmimeacceptlang(Hlex *h, char *name){	h->c->head.oklang = mimeok(h, name, 0, h->c->head.oklang);}static voidmimemodified(Hlex *h, char *){	lexhead(h);	h->c->head.ifmodsince = hdate2sec(h->wordval);}static voidmimeunmodified(Hlex *h, char *){	lexhead(h);	h->c->head.ifunmodsince = hdate2sec(h->wordval);}static voidmimematch(Hlex *h, char *){	h->c->head.ifmatch = mimeetag(h, h->c->head.ifmatch);}static voidmimenomatch(Hlex *h, char *){	h->c->head.ifnomatch = mimeetag(h, h->c->head.ifnomatch);}/* * argument is either etag or date

⌨️ 快捷键说明

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