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

📄 url.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * a NUL then someone is unescaping too many times.	 */	if(strstr(url, "%00")){		werrstr("escaped NUL in URI");		return -1;	}	m[0].sp = m[0].ep = nil;	t = &retab[REsplit];	if(!regx(t->prog, url, m, t->size)){		werrstr("malformed URI: %q", url);		return -1;	}	su->url.s = m[0].sp;	su->url.e = m[0].ep;	su->scheme.s = m[t->ind[0]].sp;	su->scheme.e = m[t->ind[0]].ep;	su->authority.s = m[t->ind[1]].sp;	su->authority.e = m[t->ind[1]].ep;	su->path.s = m[t->ind[2]].sp;	su->path.e = m[t->ind[2]].ep;	su->query.s = m[t->ind[3]].sp;	su->query.e = m[t->ind[3]].ep;	su->fragment.s = m[t->ind[4]].sp;	su->fragment.e = m[t->ind[4]].ep;	if(urldebug)		fprint(2, "split url %s into %.*q %.*q %.*q %.*q %.*q %.*q\n",			url,			su->url.s ? utfnlen(su->url.s, su->url.e-su->url.s) : 10, su->url.s ? su->url.s : "",			su->scheme.s ? utfnlen(su->scheme.s, su->scheme.e-su->scheme.s) : 10, su->scheme.s ? su->scheme.s : "",			su->authority.s ? utfnlen(su->authority.s, su->authority.e-su->authority.s) : 10, su->authority.s ? su->authority.s : "",			su->path.s ? utfnlen(su->path.s, su->path.e-su->path.s) : 10, su->path.s ? su->path.s : "",			su->query.s ? utfnlen(su->query.s, su->query.e-su->query.s) : 10, su->query.s ? su->query.s : "",			su->fragment.s ? utfnlen(su->fragment.s, su->fragment.e-su->fragment.s) : 10, su->fragment.s ? su->fragment.s : "");	return 0;}static intparse_scheme(SplitUrl *su, Url *u){	if(su->scheme.s == nil){		werrstr("missing scheme");		return -1;	}	u->scheme = estredup(su->scheme.s, su->scheme.e);	strlower(u->scheme);	if(!ismatch(REscheme, u->scheme, "scheme"))		return -1;	u->ischeme = ischeme(u->scheme);	if(urldebug)		fprint(2, "parse_scheme %s => %d\n", u->scheme, u->ischeme);	return 0;}static intparse_unknown_part(SplitUrl *su, Url *u){	char *s, *e;	assert(u->ischeme == USunknown);	assert(su->scheme.e[0] == ':');	s = su->scheme.e+1;	if(su->fragment.s){		e = su->fragment.s-1;		assert(*e == '#');	}else		e = s+strlen(s);	u->schemedata = estredup(s, e);	if(!ismatch(REunknowndata, u->schemedata, "unknown scheme data"))		return -1;	return 0;}static intparse_userinfo(char *s, char *e, Url *u){	Resub m[MaxResub];	Retab *t;	m[0].sp = s;	m[0].ep = e;	t = &retab[REuserinfo];	if(!regx(t->prog, nil, m, t->size)){		werrstr("malformed userinfo: %.*q", utfnlen(s, e-s), s);		return -1;	}	if(m[t->ind[0]].sp)		u->user = estredup(m[t->ind[0]].sp, m[t->ind[0]].ep);	if(m[t->ind[1]].sp)		u->user = estredup(m[t->ind[1]].sp, m[t->ind[1]].ep);	return 0;}static intparse_host(char *s, char *e, Url *u){	Resub m[MaxResub];	Retab *t;	m[0].sp = s;	m[0].ep = e;	t = &retab[REhost];	if(!regx(t->prog, nil, m, t->size)){		werrstr("malformed host: %.*q", utfnlen(s, e-s), s);		return -1;	}	assert(m[t->ind[0]].sp || m[t->ind[1]].sp);	if(m[t->ind[0]].sp)	/* regular */		u->host = estredup(m[t->ind[0]].sp, m[t->ind[0]].ep);	else		u->host = estredup(m[t->ind[1]].sp, m[t->ind[1]].ep);	return 0;}static intparse_authority(SplitUrl *su, Url *u){	Resub m[MaxResub];	Retab *t;	if(su->authority.s == nil)		return 0;	u->authority = estredup(su->authority.s, su->authority.e);	m[0].sp = m[0].ep = nil;	t = &retab[REauthority];	if(!regx(t->prog, u->authority, m, t->size)){		werrstr("malformed authority: %q", u->authority);		return -1;	}	if(m[t->ind[0]].sp)		if(parse_userinfo(m[t->ind[0]].sp, m[t->ind[0]].ep, u) < 0)			return -1;	if(m[t->ind[1]].sp)		if(parse_host(m[t->ind[1]].sp, m[t->ind[1]].ep, u) < 0)			return -1;	if(m[t->ind[2]].sp)		u->port = estredup(m[t->ind[2]].sp, m[t->ind[2]].ep);	return 0;}static intparse_abspath(SplitUrl *su, Url *u){	if(su->path.s == nil)		return 0;	u->path = estredup(su->path.s, su->path.e);	if(!ismatch(REabspath, u->path, "absolute path"))		return -1;	return 0;}static intparse_query(SplitUrl *su, Url *u){	if(su->query.s == nil)		return 0;	u->query = estredup(su->query.s, su->query.e);	if(!ismatch(REquery, u->query, "query"))		return -1;	return 0;}static intparse_fragment(SplitUrl *su, Url *u){	if(su->fragment.s == nil)		return 0;	u->fragment = estredup(su->fragment.s, su->fragment.e);	if(!ismatch(REfragment, u->fragment, "fragment"))		return -1;	return 0;}static intpostparse_http(Url *u){	u->open = httpopen;	u->read = httpread;	u->close = httpclose;	if(u->authority==nil){		werrstr("missing authority (hostname, port, etc.)");		return -1;	}	if(u->host == nil){		werrstr("missing host specification");		return -1;	}	if(u->path == nil){		u->http.page_spec = estrdup("/");		return 0;	}	if(!ismatch(REhttppath, u->path, "http path"))		return -1;	if(u->query){		u->http.page_spec = emalloc(strlen(u->path)+1+strlen(u->query)+1);		strcpy(u->http.page_spec, u->path);		strcat(u->http.page_spec, "?");		strcat(u->http.page_spec, u->query);	}else		u->http.page_spec = estrdup(u->path);	return 0;}static intpostparse_ftp(Url *u){	Resub m[MaxResub];	Retab *t;	if(u->authority==nil){		werrstr("missing authority (hostname, port, etc.)");		return -1;	}	if(u->query){		werrstr("unexpected \"?query\" in ftp path");		return -1;	}	if(u->host == nil){		werrstr("missing host specification");		return -1;	}	if(u->path == nil){		u->ftp.path_spec = estrdup("/");		return 0;	}	m[0].sp = m[0].ep = nil;	t = &retab[REftppath];	if(!regx(t->prog, u->path, m, t->size)){		werrstr("malformed ftp path: %q", u->path);		return -1;	}	if(m[t->ind[0]].sp){		u->ftp.path_spec = estredup(m[t->ind[0]].sp, m[t->ind[0]].ep);		if(strchr(u->ftp.path_spec, ';')){			werrstr("unexpected \";param\" in ftp path");			return -1;		}	}else		u->ftp.path_spec = estrdup("/");	if(m[t->ind[1]].sp){		u->ftp.type = estredup(m[t->ind[1]].sp, m[t->ind[1]].ep);		strlower(u->ftp.type);	}	return 0;}static intpostparse_file(Url *u){	if(u->user || u->passwd){		werrstr("user information not valid with file scheme");		return -1;	}	if(u->query){		werrstr("unexpected \"?query\" in file path");		return -1;	}	if(u->port){		werrstr("port not valid with file scheme");		return -1;	}	if(u->path == nil){		werrstr("missing path in file scheme");		return -1;	}	if(strchr(u->path, ';')){		werrstr("unexpected \";param\" in file path");		return -1;	}	if(!ismatch(REfilepath, u->path, "file path"))		return -1;	/* "localhost" is equivalent to no host spec, we'll chose the latter */	if(u->host && cistrcmp(u->host, "localhost") == 0){		free(u->host);		u->host = nil;	}	return 0;}static int (*postparse[])(Url*) = {	nil,	postparse_http,	postparse_http,	postparse_ftp,	postparse_file,};Url*parseurl(char *url, Url *base){	Url *u;	SplitUrl su;	if(urldebug)		fprint(2, "parseurl %s with base %s\n", url, base ? base->url : "<none>");	u = emalloc(sizeof(Url));	u->url = estrdup(url);	if(spliturl(u->url, &su) < 0){	Fail:		freeurl(u);		return nil;	}	/* RFC2396 sec 3.1 says relative URIs are distinguished by absent scheme */ 	if(su.scheme.s==nil){		if(urldebug)			fprint(2, "parseurl has nil scheme\n");		if(resolve_relative(&su, base, u) < 0 || spliturl(u->url, &su) < 0)			goto Fail;		if(u->ischeme == UScurrent){			/* 'u.url' refers to current document; set fragment and return */			if(parse_fragment(&su, u) < 0)				goto Fail;			return u;		}	}	if(parse_scheme(&su, u) < 0	|| parse_fragment(&su, u) < 0)		goto Fail;	if(u->ischeme == USunknown){		if(parse_unknown_part(&su, u) < 0)			goto Fail;		return u;	}	if(parse_query(&su, u) < 0	|| parse_authority(&su, u) < 0	|| parse_abspath(&su, u) < 0)		goto Fail;	if(u->ischeme < nelem(postparse) && postparse[u->ischeme])		if((*postparse[u->ischeme])(u) < 0)			goto Fail;	setmalloctag(u, getcallerpc(&url));	return u;}voidfreeurl(Url *u){	if(u == nil)		return;	free(u->url);	free(u->scheme);	free(u->schemedata);	free(u->authority);	free(u->user);	free(u->passwd);	free(u->host);	free(u->port);	free(u->path);	free(u->query);	free(u->fragment);	switch(u->ischeme){	case UShttp:		free(u->http.page_spec);		break;	case USftp:		free(u->ftp.path_spec);		free(u->ftp.type);		break;	}	free(u);}voidrewriteurl(Url *u){	char *s;	if(u->schemedata)		s = estrmanydup(u->scheme, ":", u->schemedata, nil);	else		s = estrmanydup(u->scheme, "://", 			u->user ? u->user : "",			u->passwd ? ":" : "", u->passwd ? u->passwd : "",			u->user ? "@" : "", u->host ? u->host : "", 			u->port ? ":" : "", u->port ? u->port : "",			u->path,			u->query ? "?" : "", u->query ? u->query : "",			u->fragment ? "#" : "", u->fragment ? u->fragment : "",			nil);	free(u->url);	u->url = s;}intseturlquery(Url *u, char *query){	if(query == nil){		free(u->query);		u->query = nil;		return 0;	}	if(!ismatch(REquery, query, "query"))		return -1;	free(u->query);	u->query = estrdup(query);	return 0;}static voiddupp(char **p){	if(*p)		*p = estrdup(*p);}Url*copyurl(Url *u){	Url *v;	v = emalloc(sizeof(Url));	*v = *u;	dupp(&v->url);	dupp(&v->scheme);	dupp(&v->schemedata);	dupp(&v->authority);	dupp(&v->user);	dupp(&v->passwd);	dupp(&v->host);	dupp(&v->port);	dupp(&v->path);	dupp(&v->query);	dupp(&v->fragment);	switch(v->ischeme){	case UShttp:		dupp(&v->http.page_spec);		break;	case USftp:		dupp(&v->ftp.path_spec);		dupp(&v->ftp.type);		break;	}	return v;}static intdhex(char c){	if('0' <= c && c <= '9')		return c-'0';	if('a' <= c && c <= 'f')		return c-'a'+10;	if('A' <= c && c <= 'F')		return c-'A'+10;	return 0;}char*escapeurl(char *s, int (*needesc)(int)){	int n;	char *t, *u;	Rune r;	static char *hex = "0123456789abcdef";	n = 0;	for(t=s; *t; t++)		if((*needesc)(*t))			n++;	u = emalloc(strlen(s)+2*n+1);	t = u;	for(; *s; s++){		s += chartorune(&r, s);		if(r >= 0xFF){			werrstr("URLs cannot contain Runes > 0xFF");			free(t);			return nil;		}		if((*needesc)(r)){			*u++ = '%';			*u++ = hex[(r>>4)&0xF];			*u++ = hex[r&0xF];		}else			*u++ = r;	}	*u = '\0';	return t;}char*unescapeurl(char *s){	char *r, *w;	Rune rune;	s = estrdup(s);	for(r=w=s; *r; r++){		if(*r=='%'){			r++;			if(!isxdigit(r[0]) || !isxdigit(r[1])){				werrstr("bad escape sequence '%.3s' in URL", r);				return nil;			}			if(r[0]=='0' && r[2]=='0'){				werrstr("escaped NUL in URL");				return nil;			}			rune = (dhex(r[0])<<4)|dhex(r[1]);	/* latin1 */			w += runetochar(w, &rune);			r += 2;		}else			*w++ = *r;	}	*w = '\0';	return s;}

⌨️ 快捷键说明

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