henesyinit from p9fce6d0435 years agoHistory
591 lines · 9.9 KB · Text
RawDownload
#include <alef.h>#include <bio.h>#include <auth.h>#include "httpd.h" aggr Error{	byte	*num;	byte	*concise;	byte	*verbose;}; Error errormsg[] ={	[Internal]	{"500 Internal Error", "Internal Error",		"This server could not process your request due to an interal error."},	[TempFail]	{"500 Internal Error", "Temporary Failure",		"The object %s is currently inaccessible.<p>Please try again later."},	[Unimp]	{"501 Not implemented", "Command not implemented",		"This server does not implement the %s command."},	[UnkVers]	{"501 Not Implemented", "Unknown http version",		"This server does not know how to respond to http version %s."},	[BadCont]	{"501 Not Implemented", "Impossible format",		"This server cannot produce %s in any of the formats your client accepts."},	[BadReq]	{"400 Bad Request", "Strange Request",		"Your client sent a query that this server could not understand."},	[Syntax]	{"400 Bad Request", "Garbled Syntax",		"Your client sent a query with incoherent syntax."},	[BadSearch]{"400 Bad Request", "Inapplicable Search",		"Your client sent a search that cannot be applied to %s."},	[NotFound]{"404 Not Found", "Object not found",		"The object %s does not exist on this server."},	[NoSearch]	{"403 Forbidden", "Search not supported",		"The object %s does not support the search command."},	[OnlySearch]{"403 Forbidden", "Searching Only",		"The object %s only supports the searching methods."},	[Unauth]	{"401 Unauthorized", "Unauthorized",		"You are not authorized to see the object %s."},	[OK]	{"200 OK", "everything is fine"},}; void		mimeaccept(byte*);void		mimeacceptenc(byte*);void		mimeacceptlang(byte*);void		mimeagent(byte*);void		mimefrom(byte*);void		mimeignore(byte*);void		mimemodified(byte*);void		mimeunknown(byte*); Keyword	mime[] ={	{"from",			mimefrom},	{"if-modified-since",		mimemodified},	{"accept",			mimeaccept},	{"accept-encoding",		mimeacceptenc},	{"accept-language",		mimeacceptlang},	{"user-agent",		mimeagent},	{"referer",			mimeignore},	{"authorization",		mimeignore},	{"forwarded",		mimeignore},	{"chargeto",		mimeignore},	{"x-serial-number",		mimeignore},	{"proxy-agent",		mimeignore},	{"x-afs-tokens",		mimeignore},	{nil,			mimeunknown},};  byte*	HTTPLOG = "httpd";Biobuf	bout;byte*	client = "";uint	modtime;byte*	mydomain;byte*	mysysname;byte*	namespace;Content*	okencode = nil;Content*	oklang = nil;Content*	oktype = nil;byte*	remotesys;byte*	version = "HTTP/1.0";byte	xferbuf[BufSize]; int	ALEFstack = 64*1024; intern	byte	wordval[MaxWord];intern	byte	makeup[BufSize];intern	int	tok;intern	int	eof;intern	Biobuf	bin; intern	int	getc();intern	void	ungetc();intern	int	wordcr();intern	int	wordnl();intern	void	word(byte*);intern	int	lex1(); voidanonymous(byte *namespace){	newns("none", namespace);	chdir("/");} voidhttpheaders(byte *vers){	if(vers[0] == 0)		return; 	lexinit();	tok = '\n';	alarm(15*60*1000);	while(lex() != '\n'){		if(tok == Word && lex() == ':')			parsejump(mime, strsave(wordval));		while(tok != '\n')			lex();	}	alarm(0);} Content *mimeok(byte *name, int multipart, Content *head){	byte *generic, *specific, *s;	float v; 	while(lex() != Word)		if(tok != ',')			return head; 	generic = strsave(wordval);	lex();	if(tok == '/' || multipart){		if(tok != '/')			return head;		if(lex() != Word)			return head;		specific = strsave(wordval);		lex();	}else		specific = "*";	head = mkcontent(generic, specific, head); 	for(;;){		switch(tok){		case ';':			if(lex() == Word){				s = strsave(wordval);				if(lex() != '=' || lex() != Word)					return head;				v = strtof(wordval, nil);				if(strcmp(s, "q") == 0)					head->q = v;				else if(strcmp(s, "mxb") == 0)					head->mxb = v;				else					logit("unknown %s param: %s %s",						name, s, wordval);			}			break;		case ',':			return  mimeok(name, multipart, head);		default:			return head;		}		lex();	}	return head;} voidmimeaccept(byte *name){	oktype = mimeok(name, 1, oktype);} voidmimeacceptenc(byte *name){	okencode = mimeok(name, 0, okencode);} voidmimeacceptlang(byte *name){	oklang = mimeok(name, 0, oklang);} voidmimemodified(byte *name){	lexhead();	modtime = date2sec(wordval);	if(modtime == 0)		logit("%s: %s", name, wordval);} voidmimeagent(byte *){	lexhead();	client = strsave(wordval);} voidmimefrom(byte *){	lexhead();} voidmimeignore(byte *){	lexhead();} voidmimeunknown(byte *name){	lexhead();	if(client[0])		logit("agent %s: ignoring header %s: %s ", client, name, wordval);	else		logit("ignoring header %s: %s", name, wordval);} voidparsejump(Keyword *keys, byte *k){	for(; keys->name; keys++)		if(strcmp(keys->name, k) == 0)			break;	(*keys->parse)(k);} voidlexinit(){	bin.init(0, OREAD);} intlex(){	tok = lex1();	return tok;} /* * rfc 822/rfc 1521 lexical analyzer */intern intlex1(){	int level, c; 	if(eof)		return '\n'; top:	c = getc();	switch(c){	case '(':		level = 1;		while((c = getc()) != Beof){			if(c == '\\'){				c = getc();				if(c == Beof)					return '\n';				continue;			}			if(c == '(')				level++;			else if(c == ')' && --level == 0)				break;			else if(c == '\n'){				c = getc();				if(c == Beof)					return '\n';				if(c == ')' && --level == 0)					break;				if(c != ' ' && c != '\t'){					ungetc();					return '\n';				}			}		}		goto top; 	case ' ': case '\t':		goto top; 	case '\r':		c = getc();		if(c != '\n'){			ungetc();			goto top;		} 	case '\n':		if(tok == '\n'){			eof = 1;			return '\n';		}		c = getc();		if(c == Beof)			return '\n';		if(c != ' ' && c != '\t'){			ungetc();			return '\n';		}		goto top; 	case ')':	case '<': case '>':	case '[': case ']':	case '@': case '/':	case ',': case ';': case ':': case '?': case '=':		return c; 	case '"':		word("\"");		getc();		/* skip the closing quote */		return Word; 	default:		ungetc();		word("\"()<>@,;:/[]?=\r\n \t");		return Word;	}	goto top;	return 0;	} /* * return the rest of an rfc 822, not including \r or \n * do not map to lower case */voidlexhead(){	int c, n; 	n = 0;	while((c = getc()) != Beof){		if(c == '\r')			c = wordcr();		else if(c == '\n')			c = wordnl();		if(c == '\n')			break;		if(c == '\\'){			c = getc();			if(c == Beof)				break;		} 		if(n < MaxWord-1)			wordval[n++] = c;	}	tok = '\n';	wordval[n] = 0;} intern voidword(byte *stop){	int c, n; 	n = 0;	while((c = getc()) != Beof){		if(c == '\r')			c = wordcr();		else if(c == '\n')			c = wordnl();		if(c == '\\'){			c = getc();			if(c == Beof)				break;		}else if(strchr(stop, c)){			ungetc();			wordval[n] = 0;			return;		} 		if(c >= 'A' && c <= 'Z')			c += 'a' - 'A';		if(n < MaxWord-1)			wordval[n++] = c;	}	wordval[n] = 0;} intern intwordcr(){	int c; 	c = getc();	if(c == '\n')		return wordnl();	ungetc();	return ' ';} intern intwordnl(){	int c; 	c = getc();	if(c == ' ' || c == '\t')		return c;	ungetc(); 	return '\n';} intern intgetc(void){	int c; 	c = bin.getc();	if(c == Beof){		eof = 1;		return c;	}	return c & 0x7f;} intern voidungetc(void){	bin.ungetc();} byte *urlunesc(byte *s){	byte *t, *v;	int c, n; 	v = malloc(strlen(s) + 1);	for(t = v; c = *s; s++){		if(c == '%'){			n = s[1];			if(n >= '0' && n <= '9')				n = n - '0';			else if(n >= 'A' && n <= 'F')				n = n - 'A' + 10;			else if(n >= 'a' && n <= 'f')				n = n - 'a' + 10;			else				break;			c = n;			n = s[2];			if(n >= '0' && n <= '9')				n = n - '0';			else if(n >= 'A' && n <= 'F')				n = n - 'A' + 10;			else if(n >= 'a' && n <= 'f')				n = n - 'a' + 10;			else				break;			s += 2;			c = c * 16 + n;		}		*t++ = c;	}	*t = 0;	return v;} /* * write a failure message to the net and exit */voidfail(int reason, ...){	int n; 	doprint(makeup, makeup+BufSize, errormsg[reason].verbose, ...);	snprint(xferbuf, BufSize, "<head><title>%s</title></head>\n<body><h1>%s</h1>\n%s</body>\n",		errormsg[reason].concise, errormsg[reason].concise, makeup);	n = strlen(xferbuf);	bout.print("%s %s\r\n", version, errormsg[reason].num);	bout.print("Date: %D\r\n", time());	bout.print("Server: Plan9\r\n");	bout.print("MIME-version: 1.0\r\n");	bout.print("Content-Type: text/html\r\n");	bout.print("Content-Length: %d\r\n", n);	bout.print("\r\n");	bout.write(xferbuf, n);	logit("failing: %s", makeup);	exits("failed");}

Lines 1–500 of 591.