1 #include "links.h"
2 
3 struct http_connection_info {
4 	int bl_flags;
5 	int http10;
6 	int close;
7 	off_t length;
8 	int version;
9 	int chunk_remaining;
10 };
11 
parse_http_header(unsigned char * head,unsigned char * item,unsigned char ** ptr)12 unsigned char *parse_http_header(unsigned char *head, unsigned char *item, unsigned char **ptr)
13 {
14 	unsigned char *i, *f, *g, *h;
15 	if (!head) return NULL;
16 	h = NULL;
17 	for (f = head; *f; f++) {
18 		if (*f != 10) continue;
19 		f++;
20 		for (i = item; *i && *f; i++, f++)
21 			if (upcase(*i) != upcase(*f)) goto cont;
22 		if (!*f) break;
23 		if (f[0] == ':') {
24 			while (f[1] == ' ') f++;
25 			for (g = ++f; *g >= ' '; g++) ;
26 			while (g > f && g[-1] == ' ') g--;
27 			if (h) mem_free(h);
28 			h = mem_alloc(g - f + 1);
29 			memcpy(h, f, g - f);
30 			h[g - f] = 0;
31 			if (ptr) {
32 				*ptr = f;
33 				break;
34 			}
35 			return h;
36 		}
37 		cont:;
38 		f--;
39 	}
40 	return h;
41 }
42 
parse_header_param(unsigned char * x,unsigned char * e)43 unsigned char *parse_header_param(unsigned char *x, unsigned char *e)
44 {
45 	unsigned char u;
46 	size_t le = strlen(e);
47 	int lp;
48 	unsigned char *y = x;
49 	a:
50 	if (!(y = strchr(y, ';'))) return NULL;
51 	while (*y && (*y == ';' || *y <= ' ')) y++;
52 	if (strlen(y) < le) return NULL;
53 	if (casecmp(y, e, le)) goto a;
54 	y += le;
55 	while (*y && (*y <= ' ' || *y == '=')) y++;
56 	u = ';';
57 	if (*y == '\'' || *y == '"') u = *y++;
58 	lp = 0;
59 	while (y[lp] >= ' ' && y[lp] != u) {
60 		lp++;
61 		if (lp == MAXINT) overalloc();
62 	}
63 	return memacpy(y, lp);
64 }
65 
66 /*
67  Parse string param="value", return value as new string
68  or NULL if any error.
69 */
get_param(unsigned char * e,unsigned char * name)70 unsigned char *get_param(unsigned char *e, unsigned char *name)
71 {
72 	unsigned char *n, *start;
73 	int i = 0;
74 again:
75 	while (*e && upcase(*e++) != upcase(*name));
76 	if (!*e) return NULL;
77 	n = name + 1;
78 	while (*n && upcase(*e) == upcase(*n)) e++, n++;
79 	if (*n) goto again;
80 	while (WHITECHAR(*e)) e++;
81 	if (*e++ != '=') return NULL;
82 	while (WHITECHAR(*e)) e++;
83 
84 	start = e;
85 	if (!U(*e)) while (*e && !WHITECHAR(*e)) e++;
86 	else {
87 		char uu = *e++;
88 		start++;
89 		while (*e != uu) {
90 			if (!*e) return NULL;
91 			e++;
92 		}
93 	}
94 
95 	while (start < e && *start == ' ') start++;
96 	while (start < e && *(e - 1) == ' ') e--;
97 	if (start == e) return NULL;
98 
99 	n = mem_alloc(e - start + 1);
100 	while (start < e) {
101 		if (*start < ' ') n[i] = '.';
102 		else n[i] = *start;
103 		i++; start++;
104 	}
105 	n[i] = 0;
106 	return n;
107 }
108 
get_http_code(unsigned char * head,int * code,int * version)109 int get_http_code(unsigned char *head, int *code, int *version)
110 {
111 	if (!head) return -1;
112 	while (head[0] == ' ') head++;
113 	if (upcase(head[0]) != 'H' || upcase(head[1]) != 'T' || upcase(head[2]) != 'T' ||
114 	    upcase(head[3]) != 'P') return -1;
115 	if (head[4] == '/' && head[5] >= '0' && head[5] <= '9'
116 	 && head[6] == '.' && head[7] >= '0' && head[7] <= '9' && head[8] <= ' ') {
117 		*version = (head[5] - '0') * 10 + head[7] - '0';
118 	} else *version = 0;
119 	for (head += 4; *head > ' '; head++) ;
120 	if (*head++ != ' ') return -1;
121 	if (head[0] < '1' || head [0] > '9' || head[1] < '0' || head[1] > '9' ||
122 	    head[2] < '0' || head [2] > '9') return -1;
123 	*code = (head[0]-'0')*100 + (head[1]-'0')*10 + head[2]-'0';
124 	return 0;
125 }
126 
127 struct {
128 	unsigned char *name;
129 	int bugs;
130 } buggy_servers[] = {
131 	{ "mod_czech/3.1.0", BL_HTTP10 },
132 	{ "Purveyor", BL_HTTP10 },
133 	{ "Netscape-Enterprise", BL_HTTP10 | BL_NO_ACCEPT_LANGUAGE },
134 	{ "Apache Coyote", BL_HTTP10 },
135 	{ "lighttpd", BL_HTTP10 },
136 	{ "FORPSI", BL_NO_RANGE },
137 	{ "Sausalito", BL_HTTP10 },
138 	{ NULL, 0 }
139 };
140 
check_http_server_bugs(unsigned char * url,struct http_connection_info * info,unsigned char * head)141 int check_http_server_bugs(unsigned char *url, struct http_connection_info *info, unsigned char *head)
142 {
143 	unsigned char *server;
144 	int i, bugs;
145 	if (!http_bugs.allow_blacklist || info->http10) return 0;
146 	if (!(server = parse_http_header(head, "Server", NULL))) return 0;
147 	bugs = 0;
148 	for (i = 0; buggy_servers[i].name; i++) if (strstr(server, buggy_servers[i].name)) bugs |= buggy_servers[i].bugs;
149 	mem_free(server);
150 	if (bugs && (server = get_host_name(url))) {
151 		add_blacklist_entry(server, bugs);
152 		mem_free(server);
153 		return bugs & ~BL_NO_RANGE;
154 	}
155 	return 0;
156 }
157 
http_end_request(struct connection * c,int notrunc,int nokeepalive,int state)158 void http_end_request(struct connection *c, int notrunc, int nokeepalive, int state)
159 {
160 	if (state == S__OK) {
161 		if (c->cache) {
162 			if (!notrunc) truncate_entry(c->cache, c->from, 1);
163 			c->cache->incomplete = 0;
164 		}
165 	}
166 	setcstate(c, state);
167 	if (c->info && !((struct http_connection_info *)c->info)->close
168 #ifdef HAVE_SSL
169 	 && !c->ssl /* We won't keep alive ssl connections */
170 #endif
171 	 && !nokeepalive
172 	 && (!http_bugs.bug_post_no_keepalive || !strchr(c->url, POST_CHAR))) {
173 		add_keepalive_socket(c, HTTP_KEEPALIVE_TIMEOUT, 0);
174 	} else {
175 		abort_connection(c);
176 	}
177 }
178 
179 void http_send_header(struct connection *);
180 
http_func(struct connection * c)181 void http_func(struct connection *c)
182 {
183 	/*setcstate(c, S_CONN);*/
184 	/*set_timeout(c);*/
185 	if (get_keepalive_socket(c, NULL)) {
186 		int p;
187 		if ((p = get_port(c->url)) == -1) {
188 			setcstate(c, S_BAD_URL);
189 			abort_connection(c);
190 			return;
191 		}
192 		make_connection(c, p, &c->sock1, http_send_header);
193 	} else http_send_header(c);
194 }
195 
proxy_func(struct connection * c)196 void proxy_func(struct connection *c)
197 {
198 	http_func(c);
199 }
200 
201 void http_get_header(struct connection *);
202 
http_send_header(struct connection * c)203 void http_send_header(struct connection *c)
204 {
205 	static unsigned char *accept_charset = NULL;
206 	struct http_connection_info *info;
207 	int http10 = http_bugs.http10;
208 	struct cache_entry *e = NULL;
209 	unsigned char *hdr;
210 	unsigned char *h, *u, *uu, *sp;
211 	int l = 0;
212 	int la;
213 	unsigned char *post;
214 	unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
215 	set_timeout(c);
216 	info = mem_alloc(sizeof(struct http_connection_info));
217 	memset(info, 0, sizeof(struct http_connection_info));
218 	c->info = info;
219 	if ((h = get_host_name(host))) {
220 		info->bl_flags = get_blacklist_flags(h);
221 		mem_free(h);
222 	}
223 	if (info->bl_flags & BL_HTTP10) http10 = 1;
224 	info->http10 = http10;
225 	post = strchr(c->url, POST_CHAR);
226 	if (post) post++;
227 	hdr = init_str();
228 	if (!post) add_to_str(&hdr, &l, "GET ");
229 	else {
230 		add_to_str(&hdr, &l, "POST ");
231 		c->unrestartable = 2;
232 	}
233 	if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "/");
234 	if (!(u = get_url_data(c->url))) {
235 		http_bad_url:
236 		mem_free(hdr);
237 		http_end_request(c, 0, 1, S_BAD_URL);
238 		return;
239 	}
240 	if (post && post < u) {
241 		goto http_bad_url;
242 	}
243 	if (!post) uu = stracpy(u);
244 	else uu = memacpy(u, post - u - 1);
245 	a:
246 	for (sp = uu; *sp; sp++) if (*sp <= ' ') {
247 		unsigned char *nu = mem_alloc(strlen(uu) + 3);
248 		memcpy(nu, uu, sp - uu);
249 		sprintf(nu + (sp - uu), "%%%02X", (int)*sp);
250 		strcat(nu, sp + 1);
251 		mem_free(uu);
252 		uu = nu;
253 		goto a;
254 	}
255 	add_to_str(&hdr, &l, uu);
256 	mem_free(uu);
257 	if (!http10) add_to_str(&hdr, &l, " HTTP/1.1\r\n");
258 	else add_to_str(&hdr, &l, " HTTP/1.0\r\n");
259 	if ((h = get_host_name(host))) {
260 		add_to_str(&hdr, &l, "Host: ");
261 		add_to_str(&hdr, &l, h);
262 		mem_free(h);
263 		if ((h = get_port_str(host))) {
264 			add_to_str(&hdr, &l, ":");
265 			add_to_str(&hdr, &l, h);
266 			mem_free(h);
267 		}
268 		add_to_str(&hdr, &l, "\r\n");
269 	}
270 	add_to_str(&hdr, &l, "User-Agent: Links (" VERSION_STRING "; ");
271 	add_to_str(&hdr, &l, system_name);
272 	add_to_str(&hdr, &l, "; ");
273 	add_to_str(&hdr, &l, compiler_name);
274 	add_to_str(&hdr, &l, "; ");
275 	if (!list_empty(terminals)) {
276 		add_to_str(&hdr, &l, "text");
277 	} else {
278 		add_to_str(&hdr, &l, "dump");
279 	}
280 	add_to_str(&hdr, &l, ")\r\n");
281 	add_to_str(&hdr, &l, "Accept: */*\r\n");
282 	if (!(accept_charset)) {
283 		int i;
284 		unsigned char *cs, *ac;
285 		int aclen = 0;
286 		ac = init_str();
287 		for (i = 0; (cs = get_cp_mime_name(i)); i++) {
288 			if (aclen) add_to_str(&ac, &aclen, ",");
289 			else add_to_str(&ac, &aclen, "Accept-Charset: ");
290 			add_to_str(&ac, &aclen, cs);
291 		}
292 		if (aclen) add_to_str(&ac, &aclen, "\r\n");
293 		if ((accept_charset = malloc(strlen(ac) + 1))) strcpy(accept_charset, ac);
294 		else accept_charset = "";
295 		mem_free(ac);
296 	}
297 	if (!(info->bl_flags & BL_NO_CHARSET) && !http_bugs.no_accept_charset) add_to_str(&hdr, &l, accept_charset);
298 	if (!(info->bl_flags & BL_NO_ACCEPT_LANGUAGE)) {
299 		add_to_str(&hdr, &l, "Accept-Language: ");
300 		la = l;
301 		add_to_str(&hdr, &l, _(TEXT_(T__ACCEPT_LANGUAGE), NULL));
302 		add_to_str(&hdr, &l, ", ");
303 		if (!strstr(hdr + la, "en,") && !strstr(hdr + la, "en;")) add_to_str(&hdr, &l, "en;q=0.2, ");
304 		add_to_str(&hdr, &l, "*;q=0.1\r\n");
305 	}
306 	/*add_to_str(&hdr, &l, "DNT: 1\r\n");*/
307 	if (!http10) {
308 		if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "Connection: ");
309 		else add_to_str(&hdr, &l, "Proxy-Connection: ");
310 		if (!post || !http_bugs.bug_post_no_keepalive) add_to_str(&hdr, &l, "Keep-Alive\r\n");
311 		else add_to_str(&hdr, &l, "close\r\n");
312 	}
313 	if ((e = c->cache)) {
314 		int code, vers;
315 		if (get_http_code(e->head, &code, &vers) || code >= 400) goto skip_ifmod_and_range;
316 		if (!e->incomplete && e->head && c->no_cache <= NC_IF_MOD &&
317 		    e->last_modified) {
318 			add_to_str(&hdr, &l, "If-Modified-Since: ");
319 			add_to_str(&hdr, &l, e->last_modified);
320 			add_to_str(&hdr, &l, "\r\n");
321 		}
322 	}
323 	if (c->from && (c->est_length == -1 || c->from < c->est_length) && c->no_cache < NC_IF_MOD && !(info->bl_flags & BL_NO_RANGE)) {
324 		add_to_str(&hdr, &l, "Range: bytes=");
325 		add_num_to_str(&hdr, &l, c->from);
326 		add_to_str(&hdr, &l, "-\r\n");
327 	}
328 	skip_ifmod_and_range:
329 	if (c->no_cache >= NC_PR_NO_CACHE) add_to_str(&hdr, &l, "Pragma: no-cache\r\nCache-Control: no-cache\r\n");
330 	if (post) {
331 		unsigned char *pd = strchr(post, '\n');
332 		if (pd) {
333 			add_to_str(&hdr, &l, "Content-Type: ");
334 			add_bytes_to_str(&hdr, &l, post, pd - post);
335 			add_to_str(&hdr, &l, "\r\n");
336 			post = pd + 1;
337 		}
338 		add_to_str(&hdr, &l, "Content-Length: ");
339 		add_num_to_str(&hdr, &l, strlen(post) / 2);
340 		add_to_str(&hdr, &l, "\r\n");
341 	}
342 	send_cookies(&hdr, &l, host);
343 	add_to_str(&hdr, &l, "\r\n");
344 	if (post) {
345 		while (post[0] && post[1]) {
346 			int h1, h2;
347 			h1 = post[0] <= '9' ? post[0] - '0' : post[0] >= 'A' ? upcase(post[0]) - 'A' + 10 : 0;
348 			if (h1 < 0 || h1 >= 16) h1 = 0;
349 			h2 = post[1] <= '9' ? post[1] - '0' : post[1] >= 'A' ? upcase(post[1]) - 'A' + 10 : 0;
350 			if (h2 < 0 || h2 >= 16) h2 = 0;
351 			add_chr_to_str(&hdr, &l, h1 * 16 + h2);
352 			post += 2;
353 		}
354 	}
355 	write_to_socket(c, c->sock1, hdr, l, http_get_header);
356 	mem_free(hdr);
357 	setcstate(c, S_SENT);
358 }
359 
is_line_in_buffer(struct read_buffer * rb)360 int is_line_in_buffer(struct read_buffer *rb)
361 {
362 	int l;
363 	for (l = 0; l < rb->len; l++) {
364 		if (rb->data[l] == 10) return l + 1;
365 		if (l < rb->len - 1 && rb->data[l] == 13 && rb->data[l + 1] == 10) return l + 2;
366 		if (l == rb->len - 1 && rb->data[l] == 13) return 0;
367 		if (rb->data[l] < ' ') return -1;
368 	}
369 	return 0;
370 }
371 
read_http_data(struct connection * c,struct read_buffer * rb)372 void read_http_data(struct connection *c, struct read_buffer *rb)
373 {
374 	struct http_connection_info *info = c->info;
375 	set_timeout(c);
376 	if (rb->close == 2) {
377 		http_end_request(c, 0, 0, S__OK);
378 		return;
379 	}
380 	if (info->length != -2) {
381 		int l = rb->len;
382 		if (info->length >= 0 && info->length < l) l = info->length;
383 		if ((off_t)(0UL + c->from + l) < 0) {
384 			setcstate(c, S_LARGE_FILE);
385 			abort_connection(c);
386 			return;
387 		}
388 		c->received += l;
389 		if (add_fragment(c->cache, c->from, rb->data, l) == 1) c->tries = 0;
390 		if (info->length >= 0) info->length -= l;
391 		c->from += l;
392 		kill_buffer_data(rb, l);
393 		if (!info->length && !rb->close) {
394 			http_end_request(c, 0, 0, S__OK);
395 			return;
396 		}
397 	} else {
398 		next_chunk:
399 		if (info->chunk_remaining == -2) {
400 			int l;
401 			if ((l = is_line_in_buffer(rb))) {
402 				if (l == -1) {
403 					setcstate(c, S_HTTP_ERROR);
404 					abort_connection(c);
405 					return;
406 				}
407 				kill_buffer_data(rb, l);
408 				if (l <= 2) {
409 					http_end_request(c, 0, 0, S__OK);
410 					return;
411 				}
412 				goto next_chunk;
413 			}
414 		} else if (info->chunk_remaining == -1) {
415 			int l;
416 			if ((l = is_line_in_buffer(rb))) {
417 				unsigned char *de;
418 				long n = 0;	/* warning, go away */
419 				if (l != -1) n = strtol(rb->data, (char **)(void *)&de, 16);
420 				if (l == -1 || n < 0 || n >= MAXINT || de == rb->data) {
421 					setcstate(c, S_HTTP_ERROR);
422 					abort_connection(c);
423 					return;
424 				}
425 				kill_buffer_data(rb, l);
426 				if (!(info->chunk_remaining = n)) info->chunk_remaining = -2;
427 				goto next_chunk;
428 			}
429 		} else {
430 			int l = info->chunk_remaining;
431 			if (l > rb->len) l = rb->len;
432 			if ((off_t)(0UL + c->from + l) < 0) {
433 				setcstate(c, S_LARGE_FILE);
434 				abort_connection(c);
435 				return;
436 			}
437 			c->received += l;
438 			if (add_fragment(c->cache, c->from, rb->data, l) == 1) c->tries = 0;
439 			info->chunk_remaining -= l;
440 			c->from += l;
441 			kill_buffer_data(rb, l);
442 			if (!info->chunk_remaining && rb->len >= 1) {
443 				if (rb->data[0] == 10) kill_buffer_data(rb, 1);
444 				else {
445 					if (rb->data[0] != 13 || (rb->len >= 2 && rb->data[1] != 10)) {
446 						setcstate(c, S_HTTP_ERROR);
447 						abort_connection(c);
448 						return;
449 					}
450 					if (rb->len < 2) goto read_more;
451 					kill_buffer_data(rb, 2);
452 				}
453 				info->chunk_remaining = -1;
454 				goto next_chunk;
455 			}
456 		}
457 
458 	}
459 	read_more:
460 	read_from_socket(c, c->sock1, rb, read_http_data);
461 	setcstate(c, S_TRANS);
462 }
463 
get_header(struct read_buffer * rb)464 int get_header(struct read_buffer *rb)
465 {
466 	int i;
467 	for (i = 0; i < rb->len; i++) {
468 		unsigned char a = rb->data[i];
469 		if (/*a < ' ' && a != 10 && a != 13*/!a) return -1;
470 		if (i < rb->len - 1 && a == 10 && rb->data[i + 1] == 10) return i + 2;
471 		if (i < rb->len - 3 && a == 13) {
472 			if (rb->data[i + 1] != 10) return -1;
473 			if (rb->data[i + 2] == 13) {
474 				if (rb->data[i + 3] != 10) return -1;
475 				return i + 4;
476 			}
477 		}
478 	}
479 	return 0;
480 }
481 
http_got_header(struct connection * c,struct read_buffer * rb)482 void http_got_header(struct connection *c, struct read_buffer *rb)
483 {
484 	off_t cf;
485 	int state = c->state != S_PROC ? S_GETH : S_PROC;
486 	unsigned char *head;
487 	unsigned char *cookie, *ch;
488 	int a, h, version;
489 	unsigned char *d;
490 	struct cache_entry *e;
491 	struct http_connection_info *info;
492 	unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
493 	set_timeout(c);
494 	info = c->info;
495 	if (rb->close == 2) {
496 		unsigned char *h;
497 		if (!c->tries && (h = get_host_name(host))) {
498 			if (info->bl_flags & BL_NO_CHARSET) {
499 				del_blacklist_entry(h, BL_NO_CHARSET);
500 			} else {
501 				add_blacklist_entry(h, BL_NO_CHARSET);
502 				c->tries = -1;
503 			}
504 			mem_free(h);
505 		}
506 		setcstate(c, S_CANT_READ);
507 		retry_connection(c);
508 		return;
509 	}
510 	rb->close = 0;
511 	again:
512 	if ((a = get_header(rb)) == -1) {
513 		setcstate(c, S_HTTP_ERROR);
514 		abort_connection(c);
515 		return;
516 	}
517 	if (!a) {
518 		read_from_socket(c, c->sock1, rb, http_got_header);
519 		setcstate(c, state);
520 		return;
521 	}
522 	if (get_http_code(rb->data, &h, &version) || h == 101) {
523 		setcstate(c, S_HTTP_ERROR);
524 		abort_connection(c);
525 		return;
526 	}
527 	head = mem_alloc(a + 1);
528 	memcpy(head, rb->data, a); head[a] = 0;
529 	if (check_http_server_bugs(host, c->info, head) && is_connection_restartable(c)) {
530 		mem_free(head);
531 		setcstate(c, S_RESTART);
532 		retry_connection(c);
533 		return;
534 	}
535 	ch = head;
536 	while ((cookie = parse_http_header(ch, "Set-Cookie", &ch))) {
537 		unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
538 		set_cookie(NULL, host, cookie);
539 		mem_free(cookie);
540 	}
541 	if (h == 100) {
542 		mem_free(head);
543 		state = S_PROC;
544 		kill_buffer_data(rb, a);
545 		goto again;
546 	}
547 	if (h < 200) {
548 		mem_free(head);
549 		setcstate(c, S_HTTP_ERROR);
550 		abort_connection(c);
551 		return;
552 	}
553 	if (h == 204) {
554 		mem_free(head);
555 		http_end_request(c, 0, 0, S_HTTP_204);
556 		return;
557 	}
558 	if (h == 304) {
559 		mem_free(head);
560 		http_end_request(c, 1, 0, S__OK);
561 		return;
562 	}
563 	if (h == 416 && c->from) {
564 		mem_free(head);
565 		http_end_request(c, 0, 1, S__OK);
566 		return;
567 	}
568 	if (!c->cache) {
569 		if (get_cache_entry(c->url, &c->cache)) {
570 			mem_free(head);
571 			setcstate(c, S_OUT_OF_MEM);
572 			abort_connection(c);
573 			return;
574 		}
575 		c->cache->refcount--;
576 	}
577 	e = c->cache;
578 	if (e->head) mem_free(e->head);
579 	e->head = head;
580 #ifdef HAVE_SSL
581 	if (c->ssl) {
582 		int l = 0;
583 		if (e->ssl_info) mem_free(e->ssl_info);
584 		e->ssl_info = init_str();
585 		add_num_to_str(&e->ssl_info, &l, SSL_get_cipher_bits(c->ssl, NULL));
586 		add_to_str(&e->ssl_info, &l, "-bit ");
587 		add_to_str(&e->ssl_info, &l, (unsigned char *)SSL_get_version(c->ssl));
588 		add_to_str(&e->ssl_info, &l, " ");
589 		add_to_str(&e->ssl_info, &l, (unsigned  char *)SSL_get_cipher_name(c->ssl));
590 	}
591 #endif
592 	if (e->redirect) mem_free(e->redirect), e->redirect = NULL;
593 	if (h == 301 || h == 302 || h == 303 || h == 307) {
594 		if ((d = parse_http_header(e->head, "Location", NULL))) {
595 			if (e->redirect) mem_free(e->redirect);
596 			e->redirect = d;
597 			e->redirect_get = h == 303;
598 		}
599 	}
600 	kill_buffer_data(rb, a);
601 	info->close = 0;
602 	info->length = -1;
603 	info->version = version;
604 	if ((d = parse_http_header(e->head, "Connection", NULL)) || (d = parse_http_header(e->head, "Proxy-Connection", NULL))) {
605 		if (!strcasecmp(d, "close")) info->close = 1;
606 		mem_free(d);
607 	} else if (version < 11) info->close = 1;
608 	cf = c->from;
609 	c->from = 0;
610 	if ((d = parse_http_header(e->head, "Content-Range", NULL))) {
611 		if (strlen(d) > 6) {
612 			d[5] = 0;
613 			if (!(strcasecmp(d, "bytes")) && d[6] >= '0' && d[6] <= '9') {
614 				my_strtoll_t f = my_strtoll(d + 6, NULL);
615 				if (f >= 0 && (off_t)f >= 0 && (off_t)f == f) c->from = f;
616 			}
617 		}
618 		mem_free(d);
619 	} else if (h == 206) {
620 /* Hmm ... some servers send 206 partial but don't send Content-Range */
621 		c->from = cf;
622 	}
623 	if (cf && !c->from && !c->unrestartable) c->unrestartable = 1;
624 	if (c->from > cf || c->from < 0) {
625 		setcstate(c, S_HTTP_ERROR);
626 		abort_connection(c);
627 		return;
628 	}
629 	if ((d = parse_http_header(e->head, "Content-Length", NULL))) {
630 		unsigned char *ep;
631 		my_strtoll_t l = my_strtoll(d, &ep);
632 		if (!*ep && l >= 0 && (off_t)l >= 0 && (off_t)l == l) {
633 			if (!info->close || version >= 11) info->length = l;
634 			if (c->from + l >= 0) c->est_length = c->from + l;
635 		}
636 		mem_free(d);
637 	}
638 	if ((d = parse_http_header(e->head, "Accept-Ranges", NULL))) {
639 		if (!strcasecmp(d, "none") && !c->unrestartable) c->unrestartable = 1;
640 		mem_free(d);
641 	} else {
642 		if (!c->unrestartable && !c->from) c->unrestartable = 1;
643 	}
644 	if (info->bl_flags & BL_NO_RANGE && !c->unrestartable) c->unrestartable = 1;
645 	if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) {
646 		if (!strcasecmp(d, "chunked")) {
647 			info->length = -2;
648 			info->chunk_remaining = -1;
649 		}
650 		mem_free(d);
651 	}
652 	if (!info->close && info->length == -1) info->close = 1;
653 	if ((d = parse_http_header(e->head, "Last-Modified", NULL))) {
654 		if (e->last_modified && strcasecmp(e->last_modified, d)) {
655 			delete_entry_content(e);
656 			if (c->from) {
657 				c->from = 0;
658 				mem_free(d);
659 				setcstate(c, S_MODIFIED);
660 				retry_connection(c);
661 				return;
662 			}
663 		}
664 		if (!e->last_modified) e->last_modified = d;
665 		else mem_free(d);
666 	}
667 	if (!e->last_modified && (d = parse_http_header(e->head, "Date", NULL)))
668 		e->last_modified = d;
669 	if (info->length == -1 || (version < 11 && info->close)) rb->close = 1;
670 	read_http_data(c, rb);
671 }
672 
http_get_header(struct connection * c)673 void http_get_header(struct connection *c)
674 {
675 	struct read_buffer *rb;
676 	set_timeout(c);
677 	if (!(rb = alloc_read_buffer(c))) return;
678 	rb->close = 1;
679 	read_from_socket(c, c->sock1, rb, http_got_header);
680 }
681