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

📄 cookies.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		if((issecure || !jar->c[i].secure) && iscookiematch(&jar->c[i], dom, path, now)){			if(cookiedebug)				fprint(2, "\tmatched\n");			addcookie(j, &jar->c[i]);		}	}	if(j->nc == 0){		closejar(j);		werrstr("no cookies found");		return nil;	}	qsort(j->c, j->nc, sizeof(j->c[0]), (int(*)(const void*, const void*))cookiecmp);	return j;}/* * RFC2109 4.3.2 security checks */static char*isbadcookie(Cookie *c, char *dom, char *path){	if(strncmp(c->path, path, strlen(c->path)) != 0)		return "cookie path is not a prefix of the request path";	if(c->explicitdom && c->dom[0] != '.')		return "cookie domain doesn't start with dot";	if(memchr(c->dom+1, '.', strlen(c->dom)-1-1) == nil)		return "cookie domain doesn't have embedded dots";	if(!isdomainmatch(dom, c->dom))		return "request host does not match cookie domain";	if(strcmp(ipattr(dom), "dom")==0	&& memchr(dom, '.', strlen(dom)-strlen(c->dom)) != nil)		return "request host contains dots before cookie domain";	return 0;}/* * Sunday, 25-Jan-2002 12:24:36 GMT * Sunday, 25 Jan 2002 12:24:36 GMT * Sun, 25 Jan 02 12:24:36 GMT */static intisleap(int year){	return year%4==0 && (year%100!=0 || year%400==0);}static uintstrtotime(char *s){	char *os;	int i;	Tm tm;	static int mday[2][12] = {		31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,		31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,	};	static char *wday[] = {		"Sunday", "Monday", "Tuesday", "Wednesday",		"Thursday", "Friday", "Saturday",	};	static char *mon[] = {		"Jan", "Feb", "Mar", "Apr", "May", "Jun",		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",	};	os = s;	/* Sunday, */	for(i=0; i<nelem(wday); i++){		if(cistrncmp(s, wday[i], strlen(wday[i])) == 0){			s += strlen(wday[i]);			break;		}		if(cistrncmp(s, wday[i], 3) == 0){			s += 3;			break;		}	}	if(i==nelem(wday)){		if(cookiedebug)			fprint(2, "bad wday (%s)\n", os);		return -1;	}	if(*s++ != ',' || *s++ != ' '){		if(cookiedebug)			fprint(2, "bad wday separator (%s)\n", os);		return -1;	}	/* 25- */	if(!isdigit(s[0]) || !isdigit(s[1]) || (s[2]!='-' && s[2]!=' ')){		if(cookiedebug)			fprint(2, "bad day of month (%s)\n", os);		return -1;	}	tm.mday = strtol(s, 0, 10);	s += 3;	/* Jan- */	for(i=0; i<nelem(mon); i++)		if(cistrncmp(s, mon[i], 3) == 0){			tm.mon = i;			s += 3;			break;		}	if(i==nelem(mon)){		if(cookiedebug)			fprint(2, "bad month (%s)\n", os);		return -1;	}	if(s[0] != '-' && s[0] != ' '){		if(cookiedebug)			fprint(2, "bad month separator (%s)\n", os);		return -1;	}	s++;	/* 2002 */	if(!isdigit(s[0]) || !isdigit(s[1])){		if(cookiedebug)			fprint(2, "bad year (%s)\n", os);		return -1;	}	tm.year = strtol(s, 0, 10);	s += 2;	if(isdigit(s[0]) && isdigit(s[1]))		s += 2;	else{		if(tm.year <= 68)			tm.year += 2000;		else			tm.year += 1900;	}	if(tm.mday==0 || tm.mday > mday[isleap(tm.year)][tm.mon]){		if(cookiedebug)			fprint(2, "invalid day of month (%s)\n", os);		return -1;	}	tm.year -= 1900;	if(*s++ != ' '){		if(cookiedebug)			fprint(2, "bad year separator (%s)\n", os);		return -1;	}	if(!isdigit(s[0]) || !isdigit(s[1]) || s[2]!=':'	|| !isdigit(s[3]) || !isdigit(s[4]) || s[5]!=':'	|| !isdigit(s[6]) || !isdigit(s[7]) || s[8]!=' '){		if(cookiedebug)			fprint(2, "bad time (%s)\n", os);		return -1;	}	tm.hour = atoi(s);	tm.min = atoi(s+3);	tm.sec = atoi(s+6);	if(tm.hour >= 24 || tm.min >= 60 || tm.sec >= 60){		if(cookiedebug)			fprint(2, "invalid time (%s)\n", os);		return -1;	}	s += 9;	if(cistrcmp(s, "GMT") != 0){		if(cookiedebug)			fprint(2, "time zone not GMT (%s)\n", os);		return -1;	}	strcpy(tm.zone, "GMT");	tm.yday = 0;	return tm2sec(&tm);}/* * skip linear whitespace.  we're a bit more lenient than RFC2616 2.2. */static char*skipspace(char *s){	while(*s=='\r' || *s=='\n' || *s==' ' || *s=='\t')		s++;	return s;}/* * Try to identify old netscape headers. * The old headers: *	- didn't allow spaces around the '=' *	- used an 'Expires' attribute *	- had no 'Version' attribute *	- had no quotes *	- allowed whitespace in values *	- apparently separated attr/value pairs with ';' exclusively */static intisnetscape(char *hdr){	char *s;	for(s=hdr; (s=strchr(s, '=')) != nil; s++){		if(isspace(s[1]) || (s > hdr && isspace(s[-1])))			return 0;		if(s[1]=='"')			return 0;	}	if(cistrstr(hdr, "version="))		return 0;	return 1;}/* * Parse HTTP response headers, adding cookies to jar. * Overwrites the headers.  May overwrite path. */static char* parsecookie(Cookie*, char*, char**, int, char*, char*);static intparsehttp(Jar *jar, char *hdr, char *dom, char *path){	static char setcookie[] = "Set-Cookie:";	char *e, *p, *nextp;	Cookie c;	int isns, n;	isns = isnetscape(hdr);	n = 0;	for(p=hdr; p; p=nextp){		p = skipspace(p);		if(*p == '\0')			break;		nextp = strchr(p, '\n');		if(nextp != nil)			*nextp++ = '\0';		if(cistrncmp(p, setcookie, strlen(setcookie)) != 0)			continue;		if(cookiedebug)			fprint(2, "%s\n", p);		p = skipspace(p+strlen(setcookie));		for(; *p; p=skipspace(p)){			if((e = parsecookie(&c, p, &p, isns, dom, path)) != nil){				if(cookiedebug)					fprint(2, "parse cookie: %s\n", e);				break;			}			if((e = isbadcookie(&c, dom, path)) != nil){				if(cookiedebug)					fprint(2, "reject cookie; %s\n", e);				continue;			}			addcookie(jar, &c);			n++;		}	}	return n;}static char*skipquoted(char *s){	/*	 * Sec 2.2 of RFC2616 defines a "quoted-string" as:	 *	 *  quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )	 *  qdtext         = <any TEXT except <">>	 *  quoted-pair    = "\" CHAR	 *	 * TEXT is any octet except CTLs, but including LWS;	 * LWS is [CR LF] 1*(SP | HT);	 * CHARs are ASCII octets 0-127;  (NOTE: we reject 0's)	 * CTLs are octets 0-31 and 127;	 */	if(*s != '"')		return s;	for(s++; 32 <= *s && *s < 127 && *s != '"'; s++)		if(*s == '\\' && *(s+1) != '\0')			s++;	return s;}static char*skiptoken(char *s){	/*	 * Sec 2.2 of RFC2616 defines a "token" as 	 *  1*<any CHAR except CTLs or separators>;	 * CHARs are ASCII octets 0-127;	 * CTLs are octets 0-31 and 127;	 * separators are "()<>@,;:\/[]?={}", double-quote, SP (32), and HT (9)	 */	while(32 <= *s && *s < 127 && strchr("()<>@,;:[]?={}\" \t\\", *s)==nil)		s++;	return s;}static char*skipvalue(char *s, int isns){	char *t;	/*	 * An RFC2109 value is an HTTP token or an HTTP quoted string.	 * Netscape servers ignore the spec and rely on semicolons, apparently.	 */	if(isns){		if((t = strchr(s, ';')) == nil)			t = s+strlen(s);		return t;	}	if(*s == '"')		return skipquoted(s);	return skiptoken(s);}/* * RMID=80b186bb64c03c65fab767f8; expires=Monday, 10-Feb-2003 04:44:39 GMT;  *	path=/; domain=.nytimes.com */static char*parsecookie(Cookie *c, char *p, char **e, int isns, char *dom, char *path){	int i, done;	char *t, *u, *attr, *val;	c->expire = ~0;	memset(c, 0, sizeof *c);	/* NAME=VALUE */	t = skiptoken(p);	c->name = p;	p = skipspace(t);	if(*p != '='){	Badname:		return "malformed cookie: no NAME=VALUE";	}	*t = '\0';	p = skipspace(p+1);	t = skipvalue(p, isns);	if(*t)		*t++ = '\0';	c->value = p;	p = skipspace(t);	if(c->name[0]=='\0' || c->value[0]=='\0')		goto Badname;	done = 0;	for(; *p && !done; p=skipspace(p)){		attr = p;		t = skiptoken(p);		u = skipspace(t);		switch(*u){		case '\0':			*t = '\0';			val = p = u;			break;		case ';':			*t = '\0';			val = "";			p = u+1;			break;		case '=':			*t = '\0';			val = skipspace(u+1);			p = skipvalue(val, isns);			if(*p==',')				done = 1;			if(*p)				*p++ = '\0';			break;		case ',':			if(!isns){				val = "";				p = u;				*p++ = '\0';				done = 1;				break;			}		default:			if(cookiedebug)				fprint(2, "syntax: %s\n", p);			return "syntax error";		}		for(i=0; i<nelem(stab); i++)			if(stab[i].ishttp && cistrcmp(stab[i].s, attr)==0)				*(char**)((uintptr)c+stab[i].offset) = val;		if(cistrcmp(attr, "expires") == 0){			if(!isns)				return "non-netscape cookie has Expires tag";			if(!val[0])				return "bad expires tag";			c->expire = strtotime(val);			if(c->expire == ~0)				return "cannot parse netscape expires tag";		}		if(cistrcmp(attr, "max-age") == 0)			c->expire = time(0)+atoi(val);		if(cistrcmp(attr, "secure") == 0)			c->secure = 1;	}	if(c->dom)		c->explicitdom = 1;	else		c->dom = dom;	if(c->path)		c->explicitpath = 1;	else{		c->path = path;		if((t = strchr(c->path, '?')) != 0)			*t = '\0';		if((t = strrchr(c->path, '/')) != 0)			*t = '\0';	}		c->netscapestyle = isns;	*e = p;	return nil;}Jar *jar;typedef struct Aux Aux;struct Aux{	char *dom;	char *path;	char *inhttp;	char *outhttp;	char *ctext;	int rdoff;};enum{	AuxBuf = 4096,	MaxCtext = 16*1024*1024,};voidcookieopen(Req *r){	char *s, *es;	int i, sz;	Aux *a;	syncjar(jar);	a = emalloc9p(sizeof(Aux));	r->fid->aux = a;	if(r->ifcall.mode&OTRUNC){		a->ctext = emalloc9p(1);		a->ctext[0] = '\0';	}else{		sz = 256*jar->nc+1024;	/* BUG should do better */		a->ctext = emalloc9p(sz);		a->ctext[0] = '\0';		s = a->ctext;		es = s+sz;		for(i=0; i<jar->nc; i++)			s = seprint(s, es, "%K\n", &jar->c[i]);	}	respond(r, nil);}voidcookieread(Req *r){	Aux *a;	a = r->fid->aux;	readstr(r, a->ctext);	respond(r, nil);}voidcookiewrite(Req *r){	Aux *a;	int sz;	a = r->fid->aux;	sz = r->ifcall.count+r->ifcall.offset;	if(sz > strlen(a->ctext)){		if(sz >= MaxCtext){			respond(r, "cookie file too large");			return;		}		a->ctext = erealloc9p(a->ctext, sz+1);		a->ctext[sz] = '\0';	}	memmove(a->ctext+r->ifcall.offset, r->ifcall.data, r->ifcall.count);	r->ofcall.count = r->ifcall.count;	respond(r, nil);}voidcookieclunk(Fid *fid){	char *p, *nextp;	Aux *a;	int i;	a = fid->aux;	if(a == nil)		return;	for(i=0; i<jar->nc; i++)		jar->c[i].mark = 1;	for(p=a->ctext; *p; p=nextp){		if((nextp = strchr(p, '\n')) != nil)			*nextp++ = '\0';		else			nextp = "";		addtojar(jar, p, 0);	}	for(i=0; i<jar->nc; i++)		if(jar->c[i].mark)			delcookie(jar, &jar->c[i]);	syncjar(jar);	free(a->dom);	free(a->path);	free(a->inhttp);	free(a->outhttp);	free(a->ctext);	free(a);}voidclosecookies(void){	closejar(jar);}voidinitcookies(char *file){	char *home;	fmtinstall('J', jarfmt);	fmtinstall('K', cookiefmt);	if(file == nil){		home = getenv("home");		if(home == nil)			sysfatal("no cookie file specified and no $home");		file = emalloc9p(strlen(home)+30);		strcpy(file, home);		strcat(file, "/lib/webcookies");	}	jar = readjar(file);	if(jar == nil)		sysfatal("readjar: %r");}voidhttpsetcookie(char *hdr, char *dom, char *path){	if(path == nil)		path = "/";	parsehttp(jar, hdr, dom, path);	syncjar(jar);}char*httpcookies(char *dom, char *path, int issecure){	char buf[1024];	Jar *j;	syncjar(jar);	j = cookiesearch(jar, dom, path, issecure);	snprint(buf, sizeof buf, "%J", j);	closejar(j);	return estrdup(buf);}

⌨️ 快捷键说明

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