http.c

来自「this is the file used to browse web」· C语言 代码 · 共 684 行 · 第 1/2 页

C
684
字号
#include "links.h"struct http_connection_info {	int bl_flags;	int http10;	int close;	int length;	int version;	int chunk_remaining;};unsigned char *parse_http_header(unsigned char *head, unsigned char *item, unsigned char **ptr){	unsigned char *i, *f, *g, *h;	if (!head) return NULL;	h = NULL;	for (f = head; *f; f++) {		if (*f != 10) continue;		f++;		for (i = item; *i && *f; i++, f++)			if (upcase(*i) != upcase(*f)) goto cont;		if (!*f) break;		if (f[0] == ':') {			while (f[1] == ' ') f++;			for (g = ++f; *g >= ' '; g++) ;			while (g > f && g[-1] == ' ') g--;			if (h) mem_free(h);			h = mem_alloc(g - f + 1);			memcpy(h, f, g - f);			h[g - f] = 0;			if (ptr) {				*ptr = f;				break;			}			return h;		}		cont:;		f--;	}	return h;}unsigned char *parse_header_param(unsigned char *x, unsigned char *e){	unsigned char u;	size_t le = strlen(e);	int lp;	unsigned char *y = x;	a:	if (!(y = strchr(y, ';'))) return NULL;	while (*y && (*y == ';' || *y <= ' ')) y++;	if (strlen(y) < le) return NULL;	if (casecmp(y, e, le)) goto a;	y += le;	while (*y && (*y <= ' ' || *y == '=')) y++;	u = ';';	if (*y == '\'' || *y == '"') u = *y++;	lp = 0;	while (y[lp] >= ' ' && y[lp] != u) {		lp++;		if (lp == MAXINT) overalloc();	}	return memacpy(y, lp);}/* Parse string param="value", return value as new string or NULL if any error.*/unsigned char *get_param(unsigned char *e, unsigned char *name){	unsigned char *n, *start;	int i = 0;again:		while (*e && upcase(*e++) != upcase(*name));	if (!*e) return NULL;	n = name + 1;	while (*n && upcase(*e) == upcase(*n)) e++, n++;	if (*n) goto again;	while (WHITECHAR(*e)) e++;	if (*e++ != '=') return NULL;	while (WHITECHAR(*e)) e++;	start = e;	if (!U(*e)) while (*e && !WHITECHAR(*e)) e++;	else {		char uu = *e++;		start++;		while (*e != uu) {			if (!*e) return NULL;			e++;		}	}		while (start < e && *start == ' ') start++;	while (start < e && *(e - 1) == ' ') e--;	if (start == e) return NULL;		n = mem_alloc(e - start + 1);	while (start < e) {		if (*start < ' ') n[i] = '.';		else n[i] = *start;		i++; start++;	}	n[i] = 0;	return n;}static int get_http_code(unsigned char *head, int *code, int *version){	while (head[0] == ' ') head++;	if (upcase(head[0]) != 'H' || upcase(head[1]) != 'T' || upcase(head[2]) != 'T' ||	    upcase(head[3]) != 'P') return -1;	if (head[4] == '/' && head[5] >= '0' && head[5] <= '9'	 && head[6] == '.' && head[7] >= '0' && head[7] <= '9' && head[8] <= ' ') {		*version = (head[5] - '0') * 10 + head[7] - '0';	} else *version = 0;	for (head += 4; *head > ' '; head++) ;	if (*head++ != ' ') return -1;	if (head[0] < '1' || head [0] > '9' || head[1] < '0' || head[1] > '9' ||	    head[2] < '0' || head [2] > '9') return -1;	*code = (head[0]-'0')*100 + (head[1]-'0')*10 + head[2]-'0';	return 0;}struct {	unsigned char *name;	int bugs;} buggy_servers[] = {	{ "mod_czech/3.1.0", BL_HTTP10 },	{ "Purveyor", BL_HTTP10 },	{ "Netscape-Enterprise", BL_HTTP10 | BL_NO_ACCEPT_LANGUAGE },	{ "Apache Coyote", BL_HTTP10 },	{ "lighttpd", BL_HTTP10 },	{ "FORPSI", BL_NO_RANGE },
	{ NULL, 0 }};int check_http_server_bugs(unsigned char *url, struct http_connection_info *info, unsigned char *head){	unsigned char *server;	int i, bugs;	if (!http_bugs.allow_blacklist || info->http10) return 0;	if (!(server = parse_http_header(head, "Server", NULL))) return 0;	bugs = 0;	for (i = 0; buggy_servers[i].name; i++) if (strstr(server, buggy_servers[i].name)) bugs |= buggy_servers[i].bugs;	mem_free(server);	if (bugs && (server = get_host_name(url))) {		add_blacklist_entry(server, bugs);		mem_free(server);		return bugs & ~BL_NO_RANGE;
	}	return 0;	}void http_end_request(struct connection *c, int notrunc){	if (c->state == S_OK) {		if (c->cache) {			if (!notrunc) truncate_entry(c->cache, c->from, 1);			c->cache->incomplete = 0;		}	}	if (c->info && !((struct http_connection_info *)c->info)->close #ifdef HAVE_SSL	&& (!c->ssl) /* We won't keep alive ssl connections */#endif	&& (!http_bugs.bug_post_no_keepalive || !strchr(c->url, POST_CHAR))) {		add_keepalive_socket(c, HTTP_KEEPALIVE_TIMEOUT);	} else abort_connection(c);}void http_send_header(struct connection *);void http_func(struct connection *c){	/*setcstate(c, S_CONN);*/	/*set_timeout(c);*/	if (get_keepalive_socket(c)) {		int p;		if ((p = get_port(c->url)) == -1) {			setcstate(c, S_INTERNAL);			abort_connection(c);			return;		}		make_connection(c, p, &c->sock1, http_send_header);	} else http_send_header(c);}void proxy_func(struct connection *c){	http_func(c);}void http_get_header(struct connection *);void http_send_header(struct connection *c){	static unsigned char *accept_charset = NULL;	struct http_connection_info *info;	int http10 = http_bugs.http10;	struct cache_entry *e = NULL;	unsigned char *hdr;	unsigned char *h, *u, *uu, *sp;	int l = 0;	int la;	unsigned char *post;	unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);	set_timeout(c);	info = mem_alloc(sizeof(struct http_connection_info));	memset(info, 0, sizeof(struct http_connection_info));	c->info = info;	if ((h = get_host_name(host))) {		info->bl_flags = get_blacklist_flags(h);		mem_free(h);	}	if (info->bl_flags & BL_HTTP10) http10 = 1;	info->http10 = http10;	post = strchr(c->url, POST_CHAR);	if (post) post++;	hdr = init_str();	if (!post) add_to_str(&hdr, &l, "GET ");	else {		add_to_str(&hdr, &l, "POST ");		c->unrestartable = 2;	}	if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "/");	if (!(u = get_url_data(c->url))) {		mem_free(hdr);		setcstate(c, S_BAD_URL);		http_end_request(c, 0);		return;	}	if (post && post < u) {		mem_free(hdr);		setcstate(c, S_BAD_URL);		http_end_request(c, 0);		return;	}	if (!post) uu = stracpy(u);	else uu = memacpy(u, post - u - 1);	a:	for (sp = uu; *sp; sp++) if (*sp <= ' ') {		unsigned char *nu = mem_alloc(strlen(uu) + 3);		memcpy(nu, uu, sp - uu);		sprintf(nu + (sp - uu), "%%%02X", (int)*sp);		strcat(nu, sp + 1);		mem_free(uu);		uu = nu;		goto a;	} else if (*sp == '\\') *sp = '/';	add_to_str(&hdr, &l, uu);	mem_free(uu);	if (!http10) add_to_str(&hdr, &l, " HTTP/1.1\r\n");	else add_to_str(&hdr, &l, " HTTP/1.0\r\n");	if ((h = get_host_name(host))) {		add_to_str(&hdr, &l, "Host: ");		add_to_str(&hdr, &l, h);		mem_free(h);		if ((h = get_port_str(host))) {			add_to_str(&hdr, &l, ":");			add_to_str(&hdr, &l, h);			mem_free(h);		}		add_to_str(&hdr, &l, "\r\n");	}	add_to_str(&hdr, &l, "User-Agent: Links (" VERSION_STRING "; ");	add_to_str(&hdr, &l, system_name);	if (!list_empty(terminals)) {		struct terminal *t = terminals.prev;		add_to_str(&hdr, &l, "; ");		add_num_to_str(&hdr, &l, t->x);		add_to_str(&hdr, &l, "x");		add_num_to_str(&hdr, &l, t->y);	}	add_to_str(&hdr, &l, ")\r\n");	add_to_str(&hdr, &l, "Accept: */*\r\n");	if (!(accept_charset)) {		int i;		unsigned char *cs, *ac;		int aclen = 0;		ac = init_str();		for (i = 0; (cs = get_cp_mime_name(i)); i++) {			if (aclen) add_to_str(&ac, &aclen, ", ");			else add_to_str(&ac, &aclen, "Accept-Charset: ");			add_to_str(&ac, &aclen, cs);		}		if (aclen) add_to_str(&ac, &aclen, "\r\n");		if ((accept_charset = malloc(strlen(ac) + 1))) strcpy(accept_charset, ac);		else accept_charset = "";		mem_free(ac);	}	if (!(info->bl_flags & BL_NO_CHARSET) && !http_bugs.no_accept_charset) add_to_str(&hdr, &l, accept_charset);	if (!(info->bl_flags & BL_NO_ACCEPT_LANGUAGE)) {		add_to_str(&hdr, &l, "Accept-Language: ");		la = l;		add_to_str(&hdr, &l, _(TEXT(T__ACCEPT_LANGUAGE), NULL));		add_to_str(&hdr, &l, ", ");		if (!strstr(hdr + la, "en,") && !strstr(hdr + la, "en;")) add_to_str(&hdr, &l, "en;q=0.2, ");		add_to_str(&hdr, &l, "*;q=0.1\r\n");	}	if (!http10) {		if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "Connection: ");		else add_to_str(&hdr, &l, "Proxy-Connection: ");		if (!post || !http_bugs.bug_post_no_keepalive) add_to_str(&hdr, &l, "Keep-Alive\r\n");		else add_to_str(&hdr, &l, "close\r\n");	}	if ((e = c->cache)) {		int code, vers;		if (get_http_code(e->head, &code, &vers) || code >= 400) goto skip_ifmod_and_range;		if (!e->incomplete && e->head && c->no_cache <= NC_IF_MOD &&		    e->last_modified) {			add_to_str(&hdr, &l, "If-Modified-Since: ");			add_to_str(&hdr, &l, e->last_modified);			add_to_str(&hdr, &l, "\r\n");		}	}	if (c->from && (c->est_length == -1 || c->from < c->est_length) && c->no_cache < NC_IF_MOD && !(info->bl_flags & BL_NO_RANGE)) {		add_to_str(&hdr, &l, "Range: bytes=");		add_num_to_str(&hdr, &l, c->from);		add_to_str(&hdr, &l, "-\r\n");	}	skip_ifmod_and_range:	if (c->no_cache >= NC_PR_NO_CACHE) add_to_str(&hdr, &l, "Pragma: no-cache\r\nCache-Control: no-cache\r\n");	if (post) {		unsigned char *pd = strchr(post, '\n');		if (pd) {			add_to_str(&hdr, &l, "Content-Type: ");			add_bytes_to_str(&hdr, &l, post, pd - post);			add_to_str(&hdr, &l, "\r\n");			post = pd + 1;		}		add_to_str(&hdr, &l, "Content-Length: ");		add_num_to_str(&hdr, &l, strlen(post) / 2);		add_to_str(&hdr, &l, "\r\n");	}	send_cookies(&hdr, &l, host);	add_to_str(&hdr, &l, "\r\n");	if (post) {		while (post[0] && post[1]) {			int h1, h2;			h1 = post[0] <= '9' ? post[0] - '0' : post[0] >= 'A' ? upcase(post[0]) - 'A' + 10 : 0;

⌨️ 快捷键说明

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