http.c

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

C
684
字号
			if (h1 < 0 || h1 >= 16) h1 = 0;			h2 = post[1] <= '9' ? post[1] - '0' : post[1] >= 'A' ? upcase(post[1]) - 'A' + 10 : 0;			if (h2 < 0 || h2 >= 16) h2 = 0;			add_chr_to_str(&hdr, &l, h1 * 16 + h2);			post += 2;		}	}	write_to_socket(c, c->sock1, hdr, l, http_get_header);	mem_free(hdr);	setcstate(c, S_SENT);}int is_line_in_buffer(struct read_buffer *rb){	int l;	for (l = 0; l < rb->len; l++) {		if (rb->data[l] == 10) return l + 1;		if (l < rb->len - 1 && rb->data[l] == 13 && rb->data[l + 1] == 10) return l + 2;		if (l == rb->len - 1 && rb->data[l] == 13) return 0;		if (rb->data[l] < ' ') return -1;	}	return 0;}void read_http_data(struct connection *c, struct read_buffer *rb){	struct http_connection_info *info = c->info;	set_timeout(c);	if (rb->close == 2) {		setcstate(c, S_OK);		http_end_request(c, 0);		return;	}	if (info->length != -2) {		int l = rb->len;		if (info->length >= 0 && info->length < l) l = info->length;		if (c->from + l < 0) {			setcstate(c, S_LARGE_FILE);			abort_connection(c);			return;		}		c->received += l;		if (add_fragment(c->cache, c->from, rb->data, l) == 1) c->tries = 0;		if (info->length >= 0) info->length -= l;		c->from += l;		kill_buffer_data(rb, l);		if (!info->length && !rb->close) {			setcstate(c, S_OK);			http_end_request(c, 0);			return;		}	} else {		next_chunk:		if (info->chunk_remaining == -2) {			int l;			if ((l = is_line_in_buffer(rb))) {				if (l == -1) {					setcstate(c, S_HTTP_ERROR);					abort_connection(c);					return;				}				kill_buffer_data(rb, l);				if (l <= 2) {					setcstate(c, S_OK);					http_end_request(c, 0);					return;				}				goto next_chunk;			}		} else if (info->chunk_remaining == -1) {			int l;			if ((l = is_line_in_buffer(rb))) {				unsigned char *de;				long n = 0;	/* warning, go away */				if (l != -1) n = strtol(rb->data, (char **)(void *)&de, 16);				if (l == -1 || n < 0 || n >= MAXINT || de == rb->data) {					setcstate(c, S_HTTP_ERROR);					abort_connection(c);					return;				}				kill_buffer_data(rb, l);				if (!(info->chunk_remaining = n)) info->chunk_remaining = -2;				goto next_chunk;			}		} else {			int l = info->chunk_remaining;			if (l > rb->len) l = rb->len;			if (c->from + l < 0) {				setcstate(c, S_LARGE_FILE);				abort_connection(c);				return;			}			c->received += l;			if (add_fragment(c->cache, c->from, rb->data, l) == 1) c->tries = 0;			info->chunk_remaining -= l;			c->from += l;			kill_buffer_data(rb, l);			if (!info->chunk_remaining && rb->len >= 1) {				if (rb->data[0] == 10) kill_buffer_data(rb, 1);				else {					if (rb->data[0] != 13 || (rb->len >= 2 && rb->data[1] != 10)) {						setcstate(c, S_HTTP_ERROR);						abort_connection(c);						return;					}					if (rb->len < 2) goto read_more;					kill_buffer_data(rb, 2);				}				info->chunk_remaining = -1;				goto next_chunk;			}		}					}	read_more:	read_from_socket(c, c->sock1, rb, read_http_data);	setcstate(c, S_TRANS);}int get_header(struct read_buffer *rb){	int i;	for (i = 0; i < rb->len; i++) {		unsigned char a = rb->data[i];		if (/*a < ' ' && a != 10 && a != 13*/!a) return -1;		if (i < rb->len - 1 && a == 10 && rb->data[i + 1] == 10) return i + 2;		if (i < rb->len - 3 && a == 13) {			if (rb->data[i + 1] != 10) return -1;			if (rb->data[i + 2] == 13) {				if (rb->data[i + 3] != 10) return -1;				return i + 4;			}		}	}	return 0;}void http_got_header(struct connection *c, struct read_buffer *rb){	int cf;	int state = c->state != S_PROC ? S_GETH : S_PROC;	unsigned char *head;	unsigned char *cookie, *ch;	int a, h, version;	unsigned char *d;	struct cache_entry *e;	struct http_connection_info *info;	unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);	set_timeout(c);	info = c->info;	if (rb->close == 2) {		unsigned char *h;		if (!c->tries && (h = get_host_name(host))) {			if (info->bl_flags & BL_NO_CHARSET) {				del_blacklist_entry(h, BL_NO_CHARSET);			} else {				add_blacklist_entry(h, BL_NO_CHARSET);				c->tries = -1;			}			mem_free(h);		}		setcstate(c, S_CANT_READ);		retry_connection(c);		return;	}	rb->close = 0;	again:	if ((a = get_header(rb)) == -1) {		setcstate(c, S_HTTP_ERROR);		abort_connection(c);		return;	}	if (!a) {		read_from_socket(c, c->sock1, rb, http_got_header);		setcstate(c, state);		return;	}	if (get_http_code(rb->data, &h, &version) || h == 101) {		setcstate(c, S_HTTP_ERROR);		abort_connection(c);		return;	}	head = mem_alloc(a + 1);	memcpy(head, rb->data, a); head[a] = 0;	if (check_http_server_bugs(host, c->info, head) && is_connection_restartable(c)) {		mem_free(head);		setcstate(c, S_RESTART);		retry_connection(c);		return;	}	ch = head;	while ((cookie = parse_http_header(ch, "Set-Cookie", &ch))) {		unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);		set_cookie(NULL, host, cookie);		mem_free(cookie);	}	if (h == 100) {		mem_free(head);		state = S_PROC;		kill_buffer_data(rb, a);		goto again;	}	if (h < 200) {		mem_free(head);		setcstate(c, S_HTTP_ERROR);		abort_connection(c);		return;	}	if (h == 304) {		mem_free(head);		setcstate(c, S_OK);		http_end_request(c, 1);		return;	}	if (h == 204) {		mem_free(head);		setcstate(c, S_HTTP_204);		http_end_request(c, 0);		return;	}	if (!c->cache && get_cache_entry(c->url, &c->cache)) {		mem_free(head);		setcstate(c, S_OUT_OF_MEM);		abort_connection(c);		return;	}	e = c->cache;	if (e->head) mem_free(e->head);	e->head = head;#ifdef HAVE_SSL	if (c->ssl) {		int l = 0;		if (e->ssl_info) mem_free(e->ssl_info);		e->ssl_info = init_str();		add_num_to_str(&e->ssl_info, &l, SSL_get_cipher_bits(c->ssl, NULL));		add_to_str(&e->ssl_info, &l, "-bit ");		add_to_str(&e->ssl_info, &l, SSL_get_cipher_version(c->ssl));		add_to_str(&e->ssl_info, &l, " ");		add_to_str(&e->ssl_info, &l, (unsigned  char *)SSL_get_cipher_name(c->ssl));	}#endif	if (e->redirect) mem_free(e->redirect), e->redirect = NULL;	if (h == 301 || h == 302 || h == 303 || h == 307) {		if ((d = parse_http_header(e->head, "Location", NULL))) {			if (e->redirect) mem_free(e->redirect);			e->redirect = d;			e->redirect_get = h == 303;		}	}	kill_buffer_data(rb, a);	info->close = 0;	info->length = -1;	info->version = version;	if ((d = parse_http_header(e->head, "Connection", NULL)) || (d = parse_http_header(e->head, "Proxy-Connection", NULL))) {		if (!strcasecmp(d, "close")) info->close = 1;		mem_free(d);	} else if (version < 11) info->close = 1;	cf = c->from;	c->from = 0;	if ((d = parse_http_header(e->head, "Content-Range", NULL))) {		if (strlen(d) > 6) {			d[5] = 0;			if (!(strcasecmp(d, "bytes")) && d[6] >= '0' && d[6] <= '9') {#if defined(HAVE_STRTOLL)				long long f = strtoll(d + 6, NULL, 10);#elif defined(HAVE_STRTOQ)				longlong f = strtoq(d + 6, NULL, 10);#else				long f = strtol(d + 6, NULL, 10);				if (f == MAXLONG) f = -1;#endif				if (f >= 0 && (off_t)f >= 0 && (off_t)f == f) c->from = f;			}		}		mem_free(d);	}	if (cf && !c->from && !c->unrestartable) c->unrestartable = 1;	if (c->from > cf || c->from < 0) {		setcstate(c, S_HTTP_ERROR);		abort_connection(c);		return;	}	if ((d = parse_http_header(e->head, "Content-Length", NULL))) {		unsigned char *ep;#if defined(HAVE_STRTOLL)		long long l = strtoll(d, (char **)(void *)&ep, 10);#elif defined(HAVE_STRTOQ)		longlong l = strtoq(d, (char **)(void *)&ep, 10);#else		long l = strtol(d, (char **)(void *)&ep, 10);		if (l == MAXLONG) l = -1;#endif		if (!*ep && l >= 0 && (off_t)l >= 0 && (off_t)l == l) {			if (!info->close || version >= 11) info->length = l;			if ((unsigned)c->from + (unsigned)l < MAXINT) c->est_length = c->from + l;		}		mem_free(d);	}	if ((d = parse_http_header(e->head, "Accept-Ranges", NULL))) {		if (!strcasecmp(d, "none") && !c->unrestartable) c->unrestartable = 1;		mem_free(d);	} else {
		if (!c->unrestartable && !c->from) c->unrestartable = 1;
	}
	if (info->bl_flags & BL_NO_RANGE && !c->unrestartable) c->unrestartable = 1;
	if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) {		if (!strcasecmp(d, "chunked")) {			info->length = -2;			info->chunk_remaining = -1;		}		mem_free(d);	}	if (!info->close && info->length == -1) info->close = 1;	if ((d = parse_http_header(e->head, "Last-Modified", NULL))) {		if (e->last_modified && strcasecmp(e->last_modified, d)) {			delete_entry_content(e);			if (c->from) {				c->from = 0;				mem_free(d);				setcstate(c, S_MODIFIED);				retry_connection(c);				return;			}		}		if (!e->last_modified) e->last_modified = d;		else mem_free(d);	}	if (!e->last_modified && (d = parse_http_header(e->head, "Date", NULL)))		e->last_modified = d;	if (info->length == -1 || (version < 11 && info->close)) rb->close = 1;	read_http_data(c, rb);}void http_get_header(struct connection *c){	struct read_buffer *rb;	set_timeout(c);	if (!(rb = alloc_read_buffer(c))) return;	rb->close = 1;	read_from_socket(c, c->sock1, rb, http_got_header);}

⌨️ 快捷键说明

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