if ((r->in_content_length && r->in_mblen) || r->in_transfer_encoding) {
if (r->protocol_minor == 0 && r->protocol_major == 1) { if (debug) log_d("suppressing '100 Continue' response (HTTP/1.0 client)"); r->send_continue = 0; } else if ((r->in_content_length && r->in_mblen) || r->in_transfer_encoding) {
static int process_headers(struct request *r){	char *l, *u, *s;	time_t i;	size_t n;	unsigned long cl;	do {		l = getline(&r->cn->header_input, 0);		if (l == 0)			return -1;	} while (*l == 0);	r->method_s = l;	u = strchr(l, ' ');	if (u == 0)		return -1;	*u++ = 0;	r->url = u;	s = strrchr(u, 'H');	if (s == 0 || s == u || s[-1] != ' ')		return -1;	r->version = s;	s[-1] = 0;	s = strchr(u, '?');	if (s) {		r->args = s + 1;		*s = 0;	}	if (parse_http_version(r) == -1) {		if (debug)			log_d("parse_http_version failed for \"%s\"", r->version);		r->status = 400;		return 0;	}	if (r->protocol_major && r->protocol_minor)		r->cn->keepalive = 1;	n = 0;	while ((l = getline(&r->cn->header_input, 1)) != 0) {		s = strchr(l, ':');		if (s == 0)			continue;		*s++ = 0;		while (*s == ' ')			++s;		if (*s == 0)			continue;		if (n < tuning.num_headers) {			r->headers[n].rh_name = l;			r->headers[n++].rh_value = s;		}		if (!strcasecmp(l, "User-agent"))			r->user_agent = s;		else if (!strcasecmp(l, "Referer"))			r->referer = s;		else if (!strcasecmp(l, "Authorization"))			r->authorization = s;		else if (!strcasecmp(l, "Host")) {			sanitize_host(s);			r->host = s;		} else if (!strcasecmp(l, "Connection"))			parse_connection_header(r, s);		else if (!strcasecmp(l, "If-Modified-Since"))			r->ims_s = s;		else if (!strcasecmp(l, "If-Unmodified-Since"))			r->ius_s = s;		else if (!strcasecmp(l, "Content-Type"))			r->in_content_type = s;		else if (!strcasecmp(l, "Content-Length"))			r->in_content_length = s;		else if (!strcasecmp(l, "Range")) {			if (r->range_s) {				log_d("multiple Range headers");				r->status = 400;				return 0;			} else				r->range_s = s;		} else if (!strcasecmp(l, "If-Range"))			r->if_range_s = s;		else if (!strcasecmp(l, "Transfer-Encoding"))			r->in_transfer_encoding = s;		else if (!strcasecmp(l, "Expect")) {			if (parse_expect_header(r, s) == -1) {				if (debug)					log_d("parse_expect_header failed for \"%s\"", s);				r->status = 417;				return 0;			}		}	}	r->nheaders = n;	s = r->method_s;	if (strcmp(s, m_get) == 0)		r->method = M_GET;	else {		if (strcmp(s, m_head) == 0)			r->method = M_HEAD;		else if (strcmp(s, m_post) == 0)			r->method = M_POST;		else {			if (debug)				log_d("method \"%s\" not implemented", s);			r->status = 501;			return 0;		}	}	s = r->url;	if (strlen(s) > STRLEN) {		if (debug)			log_d("url too long (%d > %d)", strlen(s), STRLEN);		r->status = 414;		return 0;	}	if (*s != '/') {		u = strchr(s, '/');		if (u == 0 || u[1] != '/' || u[2] == 0 || u[2] == '/') {			if (debug)				log_d("absoluteURI \"%s\" should contain a net_loc", r->url);			r->status = 400;			return 0;		}		u += 2;		s = strchr(u, '/');		if (s == 0)			strcpy(r->rhost, u);		else {			memcpy(r->rhost, u, s - u);			r->rhost[s - u] = 0;		}		r->host = r->rhost;		sanitize_host(r->host);	}	if (r->host == 0 && r->protocol_minor == 1) {		if (debug)			log_d("HTTP/1.1 request without Host");		r->status = 400;		return 0;	}	if (r->host && r->host[0] == 0) {		if (debug)			log_d("empty Host header");		r->status = 400;		return 0;	}	if (s == 0)		strcpy(r->path, "/");	else if (unescape_url(s, r->path) == -1) {		if (debug)			log_d("unescape_url failed for \"%s\"", s);		r->status = 400;		return 0;	}	if (r->protocol_major > 1 || (r->protocol_major == 1 && r->protocol_minor > 1)) {		log_d("%s: unsupported version HTTP/%d.%d", inet_ntoa(r->cn->peer.sin_addr), r->protocol_major, r->protocol_minor);		r->status = 505;		return 0;	}	if (r->in_transfer_encoding) {		if (strcasecmp(r->in_transfer_encoding, "chunked")) {			log_d("unimplemented transfer-coding \"%s\"", r->in_transfer_encoding);			r->status = 501;			return 0;		}		if (r->in_content_length) {			log_d("ignoring Content-Length header from client");			r->in_content_length = 0;		}	}	s = r->in_content_length;	if (s) {		if (*s == '-' || (cl = strtoul(s, &u, 10), u == s || *u || cl >= UINT_MAX)) {			log_d("bad Content-Length from client: \"%s\"", s);			r->status = 400;			return 0;		}		r->in_mblen = cl;	}	if (r->method == M_GET) {		s = r->ims_s;		if (s) {			i = timerfc(s);			if (i != -1)				r->ims = i;		}		s = r->ius_s;		if (s) {			i = timerfc(s);			if (i != -1)				r->ius = i;		}		s = r->if_range_s;		if (s) {			i = timerfc(s);			if (i != -1)				r->if_range = i;		}		s = r->range_s;		if (s) {			if (parse_range_header(r, s) == -1)				log_d("ignoring Range header \"%s\"", s);		}	} else if (r->method == M_POST) {		if (r->in_content_length == 0) {			if (debug)				log_d("POST: length required");			r->status = 411;			return 0;		}	}	if (r->send_continue) {		if ((r->in_content_length && r->in_mblen) || r->in_transfer_encoding) {			if (r->cn->header_input.end > r->cn->header_input.middle) {				if (debug)					log_d("suppressing '100 Continue' response (more input received)");				r->send_continue = 0;			}		} else {			if (debug)				log_d("suppressing '100 Continue' response (no body)");		}	}	return 1;}