Introduction
Introduction Statistics Contact Development Disclaimer Help
Refactor range-parsing - quark - quark web server
git clone git://git.suckless.org/quark
Log
Files
Refs
LICENSE
---
commit db4e35d3d5cbd5bfac61cfb8edadd47c4608a864
parent 6b508a0e073fd4e29540f8808d919ff72c1893fb
Author: Laslo Hunhold <[email protected]>
Date: Thu, 23 Jul 2020 18:16:08 +0200
Refactor range-parsing
Quark previously didn't really handle suffix-range-requests
(those of the form "-num", asking for the last num bytes) properly
and also did not catch the error when the lower in the range
"lower-upper" was actually larger than or equal to the size of the
requested file.
I always planned to refactor the parsing but got the motivation by
Eric Radman <[email protected]>, who kindly reported the latter bug
to me.
Signed-off-by: Laslo Hunhold <[email protected]>
Diffstat:
M http.c | 109 ++++++++++++++++++++++++-----…
1 file changed, 84 insertions(+), 25 deletions(-)
---
diff --git a/http.c b/http.c
@@ -562,36 +562,95 @@ http_send_response(int fd, struct request *r)
return http_send_status(fd, S_BAD_REQUEST);
}
*(q++) = '\0';
- if (p[0]) {
+
+ /*
+ * byte-range=first\0last...
+ * ^ ^
+ * | |
+ * p q
+ */
+
+ /*
+ * make sure we only have a single range,
+ * and not a comma separated list, which we
+ * will refuse to accept out of spite towards
+ * this horrible part of the spec
+ */
+ if (strchr(q, ',')) {
+ goto not_satisfiable;
+ }
+
+ if (p[0] != '\0') {
+ /*
+ * Range has format "first-last" or "first-",
+ * i.e. return bytes 'first' to 'last' (or the
+ * last byte if 'last' is not given),
+ * inclusively, and byte-numbering beginning at 0
+ */
lower = strtonum(p, 0, LLONG_MAX, &err);
- }
- if (!err && q[0]) {
+ if (!err) {
+ if (q[0] != '\0') {
+ upper = strtonum(q, 0, LLONG_MAX,
+ &err);
+ } else {
+ upper = st.st_size - 1;
+ }
+ }
+ if (err) {
+ /* one of the strtonum()'s failed */
+ return http_send_status(fd, S_BAD_REQUEST);
+ }
+
+ /* check ranges */
+ if (lower > upper || lower >= st.st_size) {
+ goto not_satisfiable;
+ }
+
+ /* adjust upper limit to be at most the last byte */
+ upper = MIN(upper, st.st_size - 1);
+ } else {
+ /*
+ * Range has format "-num", i.e. return the 'num'
+ * last bytes
+ */
+
+ /*
+ * use upper as a temporary storage for 'num',
+ * as we know 'upper' is st.st_size - 1
+ */
upper = strtonum(q, 0, LLONG_MAX, &err);
- }
- if (err) {
- return http_send_status(fd, S_BAD_REQUEST);
- }
+ if (err) {
+ return http_send_status(fd, S_BAD_REQUEST);
+ }
- /* check range */
- if (lower < 0 || upper < 0 || lower > upper) {
- if (dprintf(fd,
- "HTTP/1.1 %d %s\r\n"
- "Date: %s\r\n"
- "Content-Range: bytes */%zu\r\n"
- "Connection: close\r\n"
- "\r\n",
- S_RANGE_NOT_SATISFIABLE,
- status_str[S_RANGE_NOT_SATISFIABLE],
- timestamp(time(NULL), t),
- st.st_size) < 0) {
- return S_REQUEST_TIMEOUT;
+ /* determine lower */
+ if (upper > st.st_size) {
+ /* more bytes requested than we have */
+ lower = 0;
+ } else {
+ lower = st.st_size - upper;
}
- return S_RANGE_NOT_SATISFIABLE;
- }
- /* adjust upper limit */
- if (upper >= st.st_size)
- upper = st.st_size-1;
+ /* set upper to the correct value */
+ upper = st.st_size - 1;
+ }
+ goto satisfiable;
+not_satisfiable:
+ if (dprintf(fd,
+ "HTTP/1.1 %d %s\r\n"
+ "Date: %s\r\n"
+ "Content-Range: bytes */%zu\r\n"
+ "Connection: close\r\n"
+ "\r\n",
+ S_RANGE_NOT_SATISFIABLE,
+ status_str[S_RANGE_NOT_SATISFIABLE],
+ timestamp(time(NULL), t),
+ st.st_size) < 0) {
+ return S_REQUEST_TIMEOUT;
+ }
+ return S_RANGE_NOT_SATISFIABLE;
+satisfiable:
+ ;
}
/* mime */
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.