From aa62596afcc9143aa663bf834d305441cdd4cc70 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 19 May 2020 11:15:07 +0100 Subject: [PATCH 17/19] curl: Case insensitive check for accept-ranges (RHBZ#1837337). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When accessing an HTTP/2 server we read lowercase headers so the existing test for byte range support did not work. You would see an error like this: nbdkit: curl[1]: error: server does not support 'range' (byte range) requests This commit copies the bug fix which was recently added to qemu’s block/curl.c. qemu commits: commit 69032253c33ae1774233c63cedf36d32242a85fc Author: David Edmondson Date: Mon Feb 24 10:13:10 2020 +0000 block/curl: HTTP header field names are case insensitive commit 7788a319399f17476ff1dd43164c869e320820a2 Author: David Edmondson Date: Mon Feb 24 10:13:09 2020 +0000 block/curl: HTTP header fields allow whitespace around values Thanks: David Edmondson, Pino Toscano, Zi Liu (cherry picked from commit c1260ec1f6538831e10f164567b53054a2ec0c2a) --- plugins/curl/Makefile.am | 1 + plugins/curl/curl.c | 29 ++++++++++++++++++++++++----- tests/web-server.c | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/plugins/curl/Makefile.am b/plugins/curl/Makefile.am index 024ddb6d..3dbe3ca8 100644 --- a/plugins/curl/Makefile.am +++ b/plugins/curl/Makefile.am @@ -44,6 +44,7 @@ nbdkit_curl_plugin_la_SOURCES = \ nbdkit_curl_plugin_la_CPPFLAGS = \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/common/include \ -I$(top_srcdir)/common/utils \ $(NULL) nbdkit_curl_plugin_la_CFLAGS = \ diff --git a/plugins/curl/curl.c b/plugins/curl/curl.c index b1693dc0..ac30cbdd 100644 --- a/plugins/curl/curl.c +++ b/plugins/curl/curl.c @@ -57,6 +57,7 @@ #include #include "cleanup.h" +#include "ascii-ctype.h" static const char *url = NULL; static const char *user = NULL; @@ -497,12 +498,30 @@ header_cb (void *ptr, size_t size, size_t nmemb, void *opaque) { struct curl_handle *h = opaque; size_t realsize = size * nmemb; - const char *accept_line = "Accept-Ranges: bytes"; - const char *line = ptr; + const char *header = ptr; + const char *end = header + realsize; + const char *accept_ranges = "accept-ranges:"; + const char *bytes = "bytes"; - if (realsize >= strlen (accept_line) && - strncmp (line, accept_line, strlen (accept_line)) == 0) - h->accept_range = true; + if (realsize >= strlen (accept_ranges) && + strncasecmp (header, accept_ranges, strlen (accept_ranges)) == 0) { + const char *p = strchr (header, ':') + 1; + + /* Skip whitespace between the header name and value. */ + while (p < end && *p && ascii_isspace (*p)) + p++; + + if (end - p >= strlen (bytes) + && strncmp (p, bytes, strlen (bytes)) == 0) { + /* Check that there is nothing but whitespace after the value. */ + p += strlen (bytes); + while (p < end && *p && ascii_isspace (*p)) + p++; + + if (p == end || !*p) + h->accept_range = true; + } + } return realsize; } diff --git a/tests/web-server.c b/tests/web-server.c index f27ee70d..f9f10917 100644 --- a/tests/web-server.c +++ b/tests/web-server.c @@ -235,7 +235,7 @@ handle_request (int s, bool headers_only) const char response1_ok[] = "HTTP/1.1 200 OK\r\n"; const char response1_partial[] = "HTTP/1.1 206 Partial Content\r\n"; const char response2[] = - "Accept-Ranges: bytes\r\n" + "Accept-rANGES: bytes\r\n" /* See RHBZ#1837337 */ "Connection: keep-alive\r\n" "Content-Type: application/octet-stream\r\n"; char response3[64]; -- 2.18.2