aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2015-05-15 20:13:20 +0200
committerReyk Floeter <reyk@esdenera.com>2015-05-15 20:13:20 +0200
commitfbefc9a818a5ed612c0df918598057a8b551cb95 (patch)
treec072ec2d257394bb11fb1c75f43d040059245c4e
parent89b8c998b9e87423cc1cdec8603294765f6a0332 (diff)
downloadhttpd-fbefc9a818a5ed612c0df918598057a8b551cb95.tar.gz
httpd-fbefc9a818a5ed612c0df918598057a8b551cb95.zip
sync
-rw-r--r--httpd/config.c20
-rw-r--r--httpd/httpd.87
-rw-r--r--httpd/httpd.conf.57
-rw-r--r--httpd/logger.c14
-rw-r--r--httpd/parse.y4
-rw-r--r--httpd/server.c20
-rw-r--r--httpd/server_fcgi.c15
-rw-r--r--httpd/server_file.c312
-rw-r--r--httpd/server_http.c18
9 files changed, 376 insertions, 41 deletions
diff --git a/httpd/config.c b/httpd/config.c
index 2dc9159..7635c33 100644
--- a/httpd/config.c
+++ b/httpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.36 2015/02/23 11:48:41 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.37 2015/04/11 14:52:49 jsing Exp $ */
/*
* Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -212,12 +212,22 @@ config_setserver(struct httpd *env, struct server *srv)
fd = -1;
else if ((fd = dup(srv->srv_s)) == -1)
return (-1);
- proc_composev_imsg(ps, id, n,
- IMSG_CFG_SERVER, fd, iov, c);
+ if (proc_composev_imsg(ps, id, n,
+ IMSG_CFG_SERVER, fd, iov, c) != 0) {
+ log_warn("%s: failed to compose "
+ "IMSG_CFG_SERVER imsg for `%s'",
+ __func__, srv->srv_conf.name);
+ return (-1);
+ }
}
} else {
- proc_composev_imsg(ps, id, -1, IMSG_CFG_SERVER, -1,
- iov, c);
+ if (proc_composev_imsg(ps, id, -1, IMSG_CFG_SERVER, -1,
+ iov, c) != 0) {
+ log_warn("%s: failed to compose "
+ "IMSG_CFG_SERVER imsg for `%s'",
+ __func__, srv->srv_conf.name);
+ return (-1);
+ }
}
}
diff --git a/httpd/httpd.8 b/httpd/httpd.8
index eb35096..fcb3e42 100644
--- a/httpd/httpd.8
+++ b/httpd/httpd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.8,v 1.50 2015/02/24 07:56:06 bentley Exp $
+.\" $OpenBSD: httpd.8,v 1.51 2015/03/26 19:16:57 jmc Exp $
.\"
.\" Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: February 24 2015 $
+.Dd $Mdocdate: March 26 2015 $
.Dt HTTPD 8
.Os
.Sh NAME
@@ -85,7 +85,8 @@ Default access log file.
Default error log file.
.El
.Sh SEE ALSO
-.Xr httpd.conf 5
+.Xr httpd.conf 5 ,
+.Xr slowcgi 8
.Sh HISTORY
The
.Nm
diff --git a/httpd/httpd.conf.5 b/httpd/httpd.conf.5
index 578e490..26d6798 100644
--- a/httpd/httpd.conf.5
+++ b/httpd/httpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.conf.5,v 1.56 2015/03/11 21:52:20 reyk Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.57 2015/03/26 19:16:57 jmc Exp $
.\"
.\" Copyright (c) 2014, 2015 Reyk Floeter <reyk@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 11 2015 $
+.Dd $Mdocdate: March 26 2015 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
@@ -524,7 +524,8 @@ include "/etc/nginx/mime.types"
.Ed
.Sh SEE ALSO
.Xr htpasswd 1 ,
-.Xr httpd 8
+.Xr httpd 8 ,
+.Xr slowcgi 8
.Sh AUTHORS
.An -nosplit
The
diff --git a/httpd/logger.c b/httpd/logger.c
index b4e4404..d03d954 100644
--- a/httpd/logger.c
+++ b/httpd/logger.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: logger.c,v 1.11 2015/02/08 00:00:59 reyk Exp $ */
+/* $OpenBSD: logger.c,v 1.12 2015/04/11 14:52:49 jsing Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -118,12 +118,20 @@ logger_open_file(const char *name)
iov[1].iov_base = log->log_name;
iov[1].iov_len = strlen(log->log_name) + 1;
- proc_composev_imsg(env->sc_ps, PROC_PARENT, -1, IMSG_LOG_OPEN, -1,
- iov, 2);
+ if (proc_composev_imsg(env->sc_ps, PROC_PARENT, -1, IMSG_LOG_OPEN, -1,
+ iov, 2) != 0) {
+ log_warn("%s: failed to compose IMSG_LOG_OPEN imsg", __func__);
+ goto err;
+ }
TAILQ_INSERT_TAIL(&log_files, log, log_entry);
return (log);
+
+err:
+ free(log);
+
+ return (NULL);
}
int
diff --git a/httpd/parse.y b/httpd/parse.y
index 50e51ab..0aae421 100644
--- a/httpd/parse.y
+++ b/httpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.66 2015/03/09 15:46:45 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.67 2015/04/01 04:51:15 jsg Exp $ */
/*
* Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -1907,6 +1907,8 @@ server_inherit(struct server *src, const char *name,
fatal("out of memory");
dst->srv_conf.tls_cert = NULL;
dst->srv_conf.tls_key = NULL;
+ dst->srv_conf.tls_cert_len = 0;
+ dst->srv_conf.tls_key_len = 0;
if (src->srv_conf.return_uri != NULL &&
(dst->srv_conf.return_uri =
diff --git a/httpd/server.c b/httpd/server.c
index 281d3ee..ca67a47 100644
--- a/httpd/server.c
+++ b/httpd/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.61 2015/03/15 22:08:45 florian Exp $ */
+/* $OpenBSD: server.c,v 1.63 2015/04/23 16:59:28 florian Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -852,6 +852,11 @@ server_accept(int fd, short event, void *arg)
if ((clt = calloc(1, sizeof(*clt))) == NULL)
goto err;
+ /* Pre-allocate log buffer */
+ clt->clt_log = evbuffer_new();
+ if (clt->clt_log == NULL)
+ goto err;
+
clt->clt_s = s;
clt->clt_fd = -1;
clt->clt_toread = TOREAD_UNLIMITED;
@@ -899,13 +904,6 @@ server_accept(int fd, short event, void *arg)
return;
}
- /* Pre-allocate log buffer */
- clt->clt_log = evbuffer_new();
- if (clt->clt_log == NULL) {
- server_close(clt, "failed to allocate log buffer");
- return;
- }
-
if (srv->srv_conf.flags & SRVFLAG_TLS) {
event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT|EV_READ,
server_accept_tls, &clt->clt_tv_start,
@@ -1010,7 +1008,11 @@ server_sendlog(struct server_config *srv_conf, int cmd, const char *emsg, ...)
iov[1].iov_base = msg;
iov[1].iov_len = strlen(msg) + 1;
- proc_composev_imsg(env->sc_ps, PROC_LOGGER, -1, cmd, -1, iov, 2);
+ if (proc_composev_imsg(env->sc_ps, PROC_LOGGER, -1, cmd, -1, iov,
+ 2) != 0) {
+ log_warn("%s: failed to compose imsg", __func__);
+ return;
+ }
}
void
diff --git a/httpd/server_fcgi.c b/httpd/server_fcgi.c
index 33603a0..d0a8800 100644
--- a/httpd/server_fcgi.c
+++ b/httpd/server_fcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_fcgi.c,v 1.52 2015/02/23 19:22:43 chrisz Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.53 2015/03/26 09:01:51 florian Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -652,10 +652,21 @@ server_fcgi_writeheader(struct client *clt, struct kv *hdr, void *arg)
return (-1);
}
+ /*
+ * RFC 7230 defines a header field-name as a "token" and a "token"
+ * is defined as one or more characters for which isalpha or
+ * isdigit is true plus a list of additional characters.
+ * According to RFC 3875 a CGI environment variable is created
+ * by converting all letters to upper case and replacing '-'
+ * with '_'.
+ */
for (p = name; *p != '\0'; p++) {
if (isalpha((unsigned char)*p))
*p = toupper((unsigned char)*p);
- else
+ else if (!(*p == '!' || *p == '#' || *p == '$' || *p == '%' ||
+ *p == '&' || *p == '\'' || *p == '*' || *p == '+' ||
+ *p == '.' || *p == '^' || *p == '_' || *p == '`' ||
+ *p == '|' || *p == '~' || isdigit((unsigned char)*p)))
*p = '_';
}
diff --git a/httpd/server_file.c b/httpd/server_file.c
index f697504..52e50ff 100644
--- a/httpd/server_file.c
+++ b/httpd/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.51 2015/02/12 10:05:29 reyk Exp $ */
+/* $OpenBSD: server_file.c,v 1.54 2015/05/05 11:10:13 florian Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -36,12 +36,27 @@
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
-
-int server_file_access(struct httpd *, struct client *, char *, size_t);
-int server_file_request(struct httpd *, struct client *, char *,
- struct stat *);
-int server_file_index(struct httpd *, struct client *, struct stat *);
-int server_file_method(struct client *);
+#define MAX_RANGES 4
+
+struct range {
+ off_t start;
+ off_t end;
+};
+
+int server_file_access(struct httpd *, struct client *,
+ char *, size_t);
+int server_file_request(struct httpd *, struct client *,
+ char *, struct stat *);
+int server_partial_file_request(struct httpd *, struct client *,
+ char *, struct stat *, char *);
+int server_file_index(struct httpd *, struct client *,
+ struct stat *);
+int server_file_modified_since(struct http_descriptor *,
+ struct stat *);
+int server_file_method(struct client *);
+int parse_range_spec(char *, size_t, struct range *);
+struct range *parse_range(char *, size_t, int *);
+int buffer_add_range(int, struct evbuffer *, struct range *);
int
server_file_access(struct httpd *env, struct client *clt,
@@ -50,6 +65,7 @@ server_file_access(struct httpd *env, struct client *clt,
struct http_descriptor *desc = clt->clt_descreq;
struct server_config *srv_conf = clt->clt_srv_conf;
struct stat st;
+ struct kv *r, key;
char *newpath;
int ret;
@@ -123,7 +139,13 @@ server_file_access(struct httpd *env, struct client *clt,
goto fail;
}
- return (server_file_request(env, clt, path, &st));
+ key.kv_key = "Range";
+ r = kv_find(&desc->http_headers, &key);
+ if (r != NULL)
+ return (server_partial_file_request(env, clt, path, &st,
+ r->kv_value));
+ else
+ return (server_file_request(env, clt, path, &st));
fail:
switch (errno) {
@@ -209,6 +231,9 @@ server_file_request(struct httpd *env, struct client *clt, char *path,
goto abort;
}
+ if ((ret = server_file_modified_since(clt->clt_descreq, st)) != -1)
+ return ret;
+
/* Now open the file, should be readable or we have another problem */
if ((fd = open(path, O_RDONLY)) == -1)
goto abort;
@@ -262,6 +287,143 @@ server_file_request(struct httpd *env, struct client *clt, char *path,
}
int
+server_partial_file_request(struct httpd *env, struct client *clt, char *path,
+ struct stat *st, char *range_str)
+{
+ struct http_descriptor *resp = clt->clt_descresp;
+ struct http_descriptor *desc = clt->clt_descreq;
+ struct media_type *media, multipart_media;
+ struct range *range;
+ struct evbuffer *evb = NULL;
+ size_t content_length;
+ int code = 500, fd = -1, i, nranges, ret;
+ uint32_t boundary;
+ char content_range[64];
+ const char *errstr = NULL;
+
+ /* Ignore range request for methods other than GET */
+ if (desc->http_method != HTTP_METHOD_GET)
+ return server_file_request(env, clt, path, st);
+
+ if ((range = parse_range(range_str, st->st_size, &nranges)) == NULL) {
+ code = 416;
+ (void)snprintf(content_range, sizeof(content_range),
+ "bytes */%lld", st->st_size);
+ errstr = content_range;
+ goto abort;
+ }
+
+ /* Now open the file, should be readable or we have another problem */
+ if ((fd = open(path, O_RDONLY)) == -1)
+ goto abort;
+
+ media = media_find(env->sc_mediatypes, path);
+ if ((evb = evbuffer_new()) == NULL) {
+ errstr = "failed to allocate file buffer";
+ goto abort;
+ }
+
+ if (nranges == 1) {
+ (void)snprintf(content_range, sizeof(content_range),
+ "bytes %lld-%lld/%lld", range->start, range->end,
+ st->st_size);
+ if (kv_add(&resp->http_headers, "Content-Range",
+ content_range) == NULL)
+ goto abort;
+
+ content_length = range->end - range->start + 1;
+ if (buffer_add_range(fd, evb, range) == 0)
+ goto abort;
+
+ } else {
+ content_length = 0;
+ boundary = arc4random();
+ /* Generate a multipart payload of byteranges */
+ while (nranges--) {
+ if ((i = evbuffer_add_printf(evb, "\r\n--%ud\r\n",
+ boundary)) == -1)
+ goto abort;
+
+ content_length += i;
+ if ((i = evbuffer_add_printf(evb,
+ "Content-Type: %s/%s\r\n",
+ media == NULL ? "application" : media->media_type,
+ media == NULL ?
+ "octet-stream" : media->media_subtype)) == -1)
+ goto abort;
+
+ content_length += i;
+ if ((i = evbuffer_add_printf(evb,
+ "Content-Range: bytes %lld-%lld/%lld\r\n\r\n",
+ range->start, range->end, st->st_size)) == -1)
+ goto abort;
+
+ content_length += i;
+ if (buffer_add_range(fd, evb, range) == 0)
+ goto abort;
+
+ content_length += range->end - range->start + 1;
+ range++;
+ }
+
+ if ((i = evbuffer_add_printf(evb, "\r\n--%ud--\r\n",
+ boundary)) == -1)
+ goto abort;
+
+ content_length += i;
+
+ /* prepare multipart/byteranges media type */
+ (void)strlcpy(multipart_media.media_type, "multipart",
+ sizeof(multipart_media.media_type));
+ (void)snprintf(multipart_media.media_subtype,
+ sizeof(multipart_media.media_subtype),
+ "byteranges; boundary=%ud", boundary);
+ media = &multipart_media;
+ }
+
+ ret = server_response_http(clt, 206, media, content_length,
+ MINIMUM(time(NULL), st->st_mtim.tv_sec));
+ switch (ret) {
+ case -1:
+ goto fail;
+ case 0:
+ /* Connection is already finished */
+ close(fd);
+ evbuffer_free(evb);
+ evb = NULL;
+ goto done;
+ default:
+ break;
+ }
+
+ if (server_bufferevent_write_buffer(clt, evb) == -1)
+ goto fail;
+
+ evbuffer_free(evb);
+ evb = NULL;
+
+ bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
+ if (clt->clt_persist)
+ clt->clt_toread = TOREAD_HTTP_HEADER;
+ else
+ clt->clt_toread = TOREAD_HTTP_NONE;
+ clt->clt_done = 0;
+
+ done:
+ server_reset_http(clt);
+ return (0);
+ fail:
+ bufferevent_disable(clt->clt_bev, EV_READ|EV_WRITE);
+ bufferevent_free(clt->clt_bev);
+ clt->clt_bev = NULL;
+ abort:
+ if (errstr == NULL)
+ errstr = strerror(errno);
+ server_abort_http(clt, code, errstr);
+ return (-1);
+}
+
+int
server_file_index(struct httpd *env, struct client *clt, struct stat *st)
{
char path[PATH_MAX];
@@ -352,13 +514,15 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
} else if (S_ISDIR(st->st_mode)) {
namewidth -= 1; /* trailing slash */
if (evbuffer_add_printf(evb,
- "<a href=\"%s\">%s/</a>%*s%s%20s\n",
+ "<a href=\"%s%s/\">%s/</a>%*s%s%20s\n",
+ strchr(escapeduri, ':') != NULL ? "./" : "",
escapeduri, escapedhtml,
MAXIMUM(namewidth, 0), " ", tmstr, "-") == -1)
skip = 1;
} else if (S_ISREG(st->st_mode)) {
if (evbuffer_add_printf(evb,
- "<a href=\"%s\">%s</a>%*s%s%20llu\n",
+ "<a href=\"%s%s\">%s</a>%*s%s%20llu\n",
+ strchr(escapeduri, ':') != NULL ? "./" : "",
escapeduri, escapedhtml,
MAXIMUM(namewidth, 0), " ",
tmstr, st->st_size) == -1)
@@ -467,3 +631,131 @@ server_file_error(struct bufferevent *bev, short error, void *arg)
server_close(clt, "unknown event error");
return;
}
+
+int
+server_file_modified_since(struct http_descriptor * desc, struct stat * st)
+{
+ struct kv key, *since;
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(struct tm));
+
+ key.kv_key = "If-Modified-Since";
+ if ((since = kv_find(&desc->http_headers, &key)) != NULL &&
+ since->kv_value != NULL) {
+ if (strptime(since->kv_value, "%a, %d %h %Y %T %Z", &tm) !=
+ NULL && timegm(&tm) >= st->st_mtim.tv_sec) {
+ return (304);
+ }
+ }
+
+ return (-1);
+}
+
+struct range *
+parse_range(char *str, size_t file_sz, int *nranges)
+{
+ static struct range ranges[MAX_RANGES];
+ int i = 0;
+ char *p, *q;
+
+ /* Extract range unit */
+ if ((p = strchr(str, '=')) == NULL)
+ return (NULL);
+
+ *p++ = '\0';
+ /* Check if it's a bytes range spec */
+ if (strcmp(str, "bytes") != 0)
+ return (NULL);
+
+ while ((q = strchr(p, ',')) != NULL) {
+ *q++ = '\0';
+
+ /* Extract start and end positions */
+ if (parse_range_spec(p, file_sz, &ranges[i]) == 0)
+ continue;
+
+ i++;
+ if (i == MAX_RANGES)
+ return (NULL);
+
+ p = q;
+ }
+
+ if (parse_range_spec(p, file_sz, &ranges[i]) != 0)
+ i++;
+
+ *nranges = i;
+ return (i ? ranges : NULL);
+}
+
+int
+parse_range_spec(char *str, size_t size, struct range *r)
+{
+ size_t start_str_len, end_str_len;
+ char *p, *start_str, *end_str;
+ const char *errstr;
+
+ if ((p = strchr(str, '-')) == NULL)
+ return (0);
+
+ *p++ = '\0';
+ start_str = str;
+ end_str = p;
+ start_str_len = strlen(start_str);
+ end_str_len = strlen(end_str);
+
+ /* Either 'start' or 'end' is optional but not both */
+ if ((start_str_len == 0) && (end_str_len == 0))
+ return (0);
+
+ if (end_str_len) {
+ r->end = strtonum(end_str, 0, LLONG_MAX, &errstr);
+ if (errstr)
+ return (0);
+
+ if ((size_t)r->end >= size)
+ r->end = size - 1;
+ } else
+ r->end = size - 1;
+
+ if (start_str_len) {
+ r->start = strtonum(start_str, 0, LLONG_MAX, &errstr);
+ if (errstr)
+ return (0);
+
+ if ((size_t)r->start >= size)
+ return (0);
+ } else {
+ r->start = size - r->end;
+ r->end = size - 1;
+ }
+
+ if (r->end < r->start)
+ return (0);
+
+ return (1);
+}
+
+int
+buffer_add_range(int fd, struct evbuffer *evb, struct range *range)
+{
+ char buf[BUFSIZ];
+ size_t n, range_sz;
+ ssize_t nread;
+
+ if (lseek(fd, range->start, SEEK_SET) == -1)
+ return (0);
+
+ range_sz = range->end - range->start + 1;
+ while (range_sz) {
+ n = MINIMUM(range_sz, sizeof(buf));
+ if ((nread = read(fd, buf, n)) == -1)
+ return (0);
+
+ evbuffer_add(evb, buf, nread);
+ range_sz -= nread;
+ }
+
+ return (1);
+}
diff --git a/httpd/server_http.c b/httpd/server_http.c
index b63fc22..7b65a5e 100644
--- a/httpd/server_http.c
+++ b/httpd/server_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_http.c,v 1.75 2015/02/23 18:43:18 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.79 2015/05/03 18:39:58 florian Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -225,7 +225,8 @@ server_read_http(struct bufferevent *bev, void *arg)
goto done;
}
- while (!clt->clt_done && (line = evbuffer_readline(src)) != NULL) {
+ while (!clt->clt_done && (line =
+ evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT)) != NULL) {
linelen = strlen(line);
/*
@@ -536,7 +537,7 @@ server_read_httpchunks(struct bufferevent *bev, void *arg)
}
switch (clt->clt_toread) {
case TOREAD_HTTP_CHUNK_LENGTH:
- line = evbuffer_readline(src);
+ line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
if (line == NULL) {
/* Ignore empty line, continue */
bufferevent_enable(bev, EV_READ);
@@ -571,7 +572,7 @@ server_read_httpchunks(struct bufferevent *bev, void *arg)
break;
case TOREAD_HTTP_CHUNK_TRAILER:
/* Last chunk is 0 bytes followed by trailer and empty line */
- line = evbuffer_readline(src);
+ line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
if (line == NULL) {
/* Ignore empty line, continue */
bufferevent_enable(bev, EV_READ);
@@ -591,7 +592,7 @@ server_read_httpchunks(struct bufferevent *bev, void *arg)
break;
case 0:
/* Chunk is terminated by an empty newline */
- line = evbuffer_readline(src);
+ line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
if (line != NULL)
free(line);
if (server_bufferevent_print(clt, "\r\n") == -1)
@@ -787,6 +788,13 @@ server_abort_http(struct client *clt, u_int code, const char *msg)
extraheader = NULL;
}
break;
+ case 416:
+ if (asprintf(&extraheader,
+ "Content-Range: %s\r\n", msg) == -1) {
+ code = 500;
+ extraheader = NULL;
+ }
+ break;
default:
/*
* Do not send details of the error. Traditionally,