diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c index 82a3c5e451a..eed466018e3 100644 --- a/lib/libfetch/fetch.c +++ b/lib/libfetch/fetch.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -443,15 +444,25 @@ fetchParseURL(const char *URL) if (strcmp(u->scheme, SCHEME_HTTP) == 0 || strcmp(u->scheme, SCHEME_HTTPS) == 0) { const char hexnums[] = "0123456789abcdef"; + bool in_query_string = false; /* percent-escape whitespace. */ + /* Some servers do not handle '+' properly. In the path it must be + * literal. In the query string it can be an encoded space. + * Percent-escape the '+' in the path to be unambiguous to the server. + * https://www.w3.org/Addressing/URL/4_URI_Recommentations.html + * https://forums.aws.amazon.com/thread.jspa?threadID=55746 + */ if ((doc = malloc(strlen(p) * 3 + 1)) == NULL) { fetch_syserr(); goto ouch; } u->doc = doc; while (*p != '\0') { - if (!isspace((unsigned char)*p)) { + if (*p == '?') { + in_query_string = true; + } + if (!isspace((unsigned char)*p) && (in_query_string || *p != '+')) { *doc++ = *p++; } else { *doc++ = '%';